LCOV - code coverage report
Current view: top level - libelf - elf_getdata.c (source / functions) Coverage Total Hit
Test: elfutils-0.193 Lines: 87.6 % 201 176
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: 82.0 % 128 105

             Branch data     Line data    Source code
       1                 :             : /* Return the next data element from the section after possibly converting it.
       2                 :             :    Copyright (C) 1998-2005, 2006, 2007, 2015, 2016 Red Hat, Inc.
       3                 :             :    Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
       4                 :             :    This file is part of elfutils.
       5                 :             :    Written by Ulrich Drepper <drepper@redhat.com>, 1998.
       6                 :             : 
       7                 :             :    This file is free software; you can redistribute it and/or modify
       8                 :             :    it under the terms of either
       9                 :             : 
      10                 :             :      * the GNU Lesser General Public License as published by the Free
      11                 :             :        Software Foundation; either version 3 of the License, or (at
      12                 :             :        your option) any later version
      13                 :             : 
      14                 :             :    or
      15                 :             : 
      16                 :             :      * the GNU General Public License as published by the Free
      17                 :             :        Software Foundation; either version 2 of the License, or (at
      18                 :             :        your option) any later version
      19                 :             : 
      20                 :             :    or both in parallel, as here.
      21                 :             : 
      22                 :             :    elfutils is distributed in the hope that it will be useful, but
      23                 :             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      24                 :             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      25                 :             :    General Public License for more details.
      26                 :             : 
      27                 :             :    You should have received copies of the GNU General Public License and
      28                 :             :    the GNU Lesser General Public License along with this program.  If
      29                 :             :    not, see <http://www.gnu.org/licenses/>.  */
      30                 :             : 
      31                 :             : #ifdef HAVE_CONFIG_H
      32                 :             : # include <config.h>
      33                 :             : #endif
      34                 :             : 
      35                 :             : #include <errno.h>
      36                 :             : #include <stddef.h>
      37                 :             : #include <string.h>
      38                 :             : 
      39                 :             : #include "libelfP.h"
      40                 :             : #include "common.h"
      41                 :             : #include "elf-knowledge.h"
      42                 :             : 
      43                 :             : 
      44                 :             : #define TYPEIDX(Sh_Type) \
      45                 :             :   (Sh_Type >= SHT_NULL && Sh_Type < SHT_NUM                                     \
      46                 :             :    ? Sh_Type                                                                  \
      47                 :             :    : (Sh_Type >= SHT_GNU_HASH && Sh_Type <= SHT_HISUNW                          \
      48                 :             :       ? SHT_NUM + Sh_Type - SHT_GNU_HASH                                      \
      49                 :             :       : 0))
      50                 :             : 
      51                 :             : /* Associate section types with libelf types.  */
      52                 :             : static const Elf_Type shtype_map[TYPEIDX (SHT_HISUNW) + 1] =
      53                 :             :   {
      54                 :             :       [SHT_SYMTAB] = ELF_T_SYM,
      55                 :             :       [SHT_RELA] = ELF_T_RELA,
      56                 :             :       [SHT_HASH] = ELF_T_WORD,
      57                 :             :       [SHT_DYNAMIC] = ELF_T_DYN,
      58                 :             :       [SHT_REL] = ELF_T_REL,
      59                 :             :       [SHT_DYNSYM] = ELF_T_SYM,
      60                 :             :       [SHT_INIT_ARRAY] = ELF_T_ADDR,
      61                 :             :       [SHT_FINI_ARRAY] = ELF_T_ADDR,
      62                 :             :       [SHT_PREINIT_ARRAY] = ELF_T_ADDR,
      63                 :             :       [SHT_GROUP] = ELF_T_WORD,
      64                 :             :       [SHT_SYMTAB_SHNDX] = ELF_T_WORD,
      65                 :             :       [SHT_NOTE] = ELF_T_NHDR, /* Need alignment to guess ELF_T_NHDR8.  */
      66                 :             :       [TYPEIDX (SHT_GNU_verdef)] = ELF_T_VDEF,
      67                 :             :       [TYPEIDX (SHT_GNU_verneed)] = ELF_T_VNEED,
      68                 :             :       [TYPEIDX (SHT_GNU_versym)] = ELF_T_HALF,
      69                 :             :       [TYPEIDX (SHT_SUNW_syminfo)] = ELF_T_SYMINFO,
      70                 :             :       [TYPEIDX (SHT_SUNW_move)] = ELF_T_MOVE,
      71                 :             :       [TYPEIDX (SHT_GNU_LIBLIST)] = ELF_T_LIB,
      72                 :             :       [TYPEIDX (SHT_GNU_HASH)] = ELF_T_GNUHASH,
      73                 :             :   };
      74                 :             : 
      75                 :             : /* Associate libelf types with their internal alignment requirements.  */
      76                 :             : const uint_fast8_t __libelf_type_aligns[ELFCLASSNUM - 1][ELF_T_NUM] =
      77                 :             :   {
      78                 :             : # define TYPE_ALIGNS(Bits)                                                    \
      79                 :             :       [ELF_T_ADDR] = __alignof__ (ElfW2(Bits,Addr)),                          \
      80                 :             :       [ELF_T_EHDR] = __alignof__ (ElfW2(Bits,Ehdr)),                          \
      81                 :             :       [ELF_T_HALF] = __alignof__ (ElfW2(Bits,Half)),                          \
      82                 :             :       [ELF_T_OFF] = __alignof__ (ElfW2(Bits,Off)),                            \
      83                 :             :       [ELF_T_PHDR] = __alignof__ (ElfW2(Bits,Phdr)),                          \
      84                 :             :       [ELF_T_SHDR] = __alignof__ (ElfW2(Bits,Shdr)),                          \
      85                 :             :       [ELF_T_SWORD] = __alignof__ (ElfW2(Bits,Sword)),                        \
      86                 :             :       [ELF_T_WORD] = __alignof__ (ElfW2(Bits,Word)),                          \
      87                 :             :       [ELF_T_XWORD] = __alignof__ (ElfW2(Bits,Xword)),                        \
      88                 :             :       [ELF_T_SXWORD] = __alignof__ (ElfW2(Bits,Sxword)),                      \
      89                 :             :       [ELF_T_SYM] = __alignof__ (ElfW2(Bits,Sym)),                            \
      90                 :             :       [ELF_T_SYMINFO] = __alignof__ (ElfW2(Bits,Syminfo)),                    \
      91                 :             :       [ELF_T_REL] = __alignof__ (ElfW2(Bits,Rel)),                            \
      92                 :             :       [ELF_T_RELA] = __alignof__ (ElfW2(Bits,Rela)),                          \
      93                 :             :       [ELF_T_DYN] = __alignof__ (ElfW2(Bits,Dyn)),                            \
      94                 :             :       [ELF_T_VDEF] = __alignof__ (ElfW2(Bits,Verdef)),                        \
      95                 :             :       [ELF_T_VDAUX] = __alignof__ (ElfW2(Bits,Verdaux)),                      \
      96                 :             :       [ELF_T_VNEED] = __alignof__ (ElfW2(Bits,Verneed)),                      \
      97                 :             :       [ELF_T_VNAUX] = __alignof__ (ElfW2(Bits,Vernaux)),                      \
      98                 :             :       [ELF_T_MOVE] = __alignof__ (ElfW2(Bits,Move)),                          \
      99                 :             :       [ELF_T_LIB] = __alignof__ (ElfW2(Bits,Lib)),                            \
     100                 :             :       [ELF_T_NHDR] = __alignof__ (ElfW2(Bits,Nhdr)),                          \
     101                 :             :       [ELF_T_AUXV] = __alignof__ (ElfW2(Bits,auxv_t)),                        \
     102                 :             :       [ELF_T_CHDR] = __alignof__ (ElfW2(Bits,Chdr)),                          \
     103                 :             :       [ELF_T_NHDR8] = 8 /* Special case for GNU Property note.  */
     104                 :             :     [ELFCLASS32 - 1] =  {
     105                 :             :         TYPE_ALIGNS (32),
     106                 :             :         [ELF_T_GNUHASH] = __alignof__ (Elf32_Word),
     107                 :             :     },
     108                 :             :     [ELFCLASS64 - 1] = {
     109                 :             :         TYPE_ALIGNS (64),
     110                 :             :         [ELF_T_GNUHASH] = __alignof__ (Elf64_Xword),
     111                 :             :     },
     112                 :             : # undef TYPE_ALIGNS
     113                 :             :   };
     114                 :             : 
     115                 :             : 
     116                 :             : Elf_Type
     117                 :             : internal_function
     118                 :     2157393 : __libelf_data_type (GElf_Ehdr *ehdr, int sh_type, GElf_Xword align)
     119                 :             : {
     120                 :             :   /* Some broken ELF ABI for 64-bit machines use the wrong hash table
     121                 :             :      entry size.  See elf-knowledge.h for more information.  */
     122   [ +  +  +  + ]:     2157393 :   if (sh_type == SHT_HASH && ehdr->e_ident[EI_CLASS] == ELFCLASS64)
     123                 :             :     {
     124   [ +  +  +  + ]:         276 :       return (SH_ENTSIZE_HASH (ehdr) == 4 ? ELF_T_WORD : ELF_T_XWORD);
     125                 :             :     }
     126                 :             :   else
     127                 :             :     {
     128   [ +  +  +  + ]:     2157117 :       Elf_Type t = shtype_map[TYPEIDX (sh_type)];
     129                 :             :       /* Special case for GNU Property notes.  */
     130         [ +  + ]:     2157117 :       if (t == ELF_T_NHDR && align == 8)
     131                 :         804 :         t = ELF_T_NHDR8;
     132                 :     2157117 :       return t;
     133                 :             :     }
     134                 :             : }
     135                 :             : 
     136                 :             : /* Convert the data in the current section.  */
     137                 :             : static void
     138                 :     1532514 : convert_data (Elf_Scn *scn, int eclass,
     139                 :             :               int data, size_t size, Elf_Type type)
     140                 :             : {
     141                 :     1532514 :   const size_t align = __libelf_type_align (eclass, type);
     142                 :             : 
     143                 :             :   /* Do we need to convert the data and/or adjust for alignment?  */
     144         [ +  + ]:     1532514 :   if (data == MY_ELFDATA || type == ELF_T_BYTE)
     145                 :             :     {
     146         [ +  + ]:     1526994 :       if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0)
     147                 :             :         /* No need to copy, we can use the raw data.  */
     148                 :     1526388 :         scn->data_base = scn->rawdata_base;
     149                 :             :       else
     150                 :             :         {
     151                 :         606 :           scn->data_base = malloc (size);
     152         [ -  + ]:         606 :           if (scn->data_base == NULL)
     153                 :             :             {
     154                 :           0 :               __libelf_seterrno (ELF_E_NOMEM);
     155                 :           0 :               return;
     156                 :             :             }
     157                 :             : 
     158                 :             :           /* The copy will be appropriately aligned for direct access.  */
     159                 :         606 :           memcpy (scn->data_base, scn->rawdata_base, size);
     160                 :             :         }
     161                 :             :     }
     162                 :             :   else
     163                 :             :     {
     164                 :        5520 :       xfct_t fp;
     165                 :             : 
     166                 :        5520 :       scn->data_base = malloc (size);
     167         [ -  + ]:        5520 :       if (scn->data_base == NULL)
     168                 :             :         {
     169                 :           0 :           __libelf_seterrno (ELF_E_NOMEM);
     170                 :           0 :           return;
     171                 :             :         }
     172                 :             : 
     173                 :             :       /* Make sure the source is correctly aligned for the conversion
     174                 :             :          function to directly access the data elements.  */
     175                 :        5520 :       char *rawdata_source;
     176         [ +  + ]:        5520 :       if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0)
     177                 :             :         rawdata_source = scn->rawdata_base;
     178                 :             :       else
     179                 :             :         {
     180                 :          40 :           rawdata_source = malloc (size);
     181         [ -  + ]:          40 :           if (rawdata_source == NULL)
     182                 :             :             {
     183                 :           0 :               __libelf_seterrno (ELF_E_NOMEM);
     184                 :           0 :               return;
     185                 :             :             }
     186                 :             : 
     187                 :             :           /* The copy will be appropriately aligned for direct access.  */
     188                 :          40 :           memcpy (rawdata_source, scn->rawdata_base, size);
     189                 :             :         }
     190                 :             : 
     191                 :             :       /* Get the conversion function.  */
     192                 :        5520 :       fp = __elf_xfctstom[eclass - 1][type];
     193                 :             : 
     194                 :        5520 :       fp (scn->data_base, rawdata_source, size, 0);
     195                 :             : 
     196         [ +  + ]:        5520 :       if (rawdata_source != scn->rawdata_base)
     197                 :          40 :         free (rawdata_source);
     198                 :             :     }
     199                 :             : 
     200                 :     1532514 :   scn->data_list.data.d.d_buf = scn->data_base;
     201                 :     1532514 :   scn->data_list.data.d.d_size = size;
     202                 :     1532514 :   scn->data_list.data.d.d_type = type;
     203                 :     1532514 :   scn->data_list.data.d.d_off = scn->rawdata.d.d_off;
     204                 :     1532514 :   scn->data_list.data.d.d_align = scn->rawdata.d.d_align;
     205                 :     1532514 :   scn->data_list.data.d.d_version = scn->rawdata.d.d_version;
     206                 :             : 
     207                 :     1532514 :   scn->data_list.data.s = scn;
     208                 :             : }
     209                 :             : 
     210                 :             : 
     211                 :             : /* Store the information for the raw data in the `rawdata' element.  */
     212                 :             : int
     213                 :             : internal_function
     214                 :     2157301 : __libelf_set_rawdata_wrlock (Elf_Scn *scn)
     215                 :             : {
     216                 :     2157301 :   Elf64_Off offset;
     217                 :     2157301 :   Elf64_Xword size;
     218                 :     2157301 :   Elf64_Xword align;
     219                 :     2157301 :   Elf64_Xword flags;
     220                 :     2157301 :   int type;
     221                 :     2157301 :   Elf *elf = scn->elf;
     222                 :             : 
     223         [ +  + ]:     2157301 :   if (elf->class == ELFCLASS32)
     224                 :             :     {
     225                 :     2486530 :       Elf32_Shdr *shdr
     226         [ +  + ]:     1243248 :         = scn->shdr.e32 ?: __elf32_getshdr_wrlock (scn);
     227                 :             : 
     228         [ -  + ]:          34 :       if (shdr == NULL)
     229                 :             :         /* Something went terribly wrong.  */
     230                 :             :         return 1;
     231                 :             : 
     232                 :     1243248 :       offset = shdr->sh_offset;
     233                 :     1243248 :       size = shdr->sh_size;
     234                 :     1243248 :       type = shdr->sh_type;
     235                 :     1243248 :       align = shdr->sh_addralign;
     236                 :     1243248 :       flags = shdr->sh_flags;
     237                 :             :     }
     238                 :             :   else
     239                 :             :     {
     240                 :     1828142 :       Elf64_Shdr *shdr
     241         [ +  + ]:      914053 :         = scn->shdr.e64 ?: __elf64_getshdr_wrlock (scn);
     242                 :             : 
     243         [ -  + ]:          36 :       if (shdr == NULL)
     244                 :             :         /* Something went terribly wrong.  */
     245                 :             :         return 1;
     246                 :             : 
     247                 :      914053 :       offset = shdr->sh_offset;
     248                 :      914053 :       size = shdr->sh_size;
     249                 :      914053 :       type = shdr->sh_type;
     250                 :      914053 :       align = shdr->sh_addralign;
     251                 :      914053 :       flags = shdr->sh_flags;
     252                 :             :     }
     253                 :             : 
     254                 :             :   /* If the section has no data (for whatever reason), leave the `d_buf'
     255                 :             :      pointer NULL.  */
     256         [ +  + ]:     2157301 :   if (size != 0 && type != SHT_NOBITS)
     257                 :             :     {
     258                 :             :       /* First a test whether the section is valid at all.  */
     259                 :     2152993 :       size_t entsize;
     260                 :             : 
     261                 :             :       /* Compressed data has a header, but then compressed data.
     262                 :             :          Make sure to set the alignment of the header explicitly,
     263                 :             :          don't trust the file alignment for the section, it is
     264                 :             :          often wrong.  */
     265         [ +  + ]:     2152993 :       if ((flags & SHF_COMPRESSED) != 0)
     266                 :             :         {
     267                 :        2632 :           entsize = 1;
     268         [ +  - ]:        2632 :           align = __libelf_type_align (elf->class, ELF_T_CHDR);
     269                 :             :         }
     270         [ +  + ]:     2150361 :       else if (type == SHT_HASH)
     271                 :             :         {
     272                 :         568 :           GElf_Ehdr ehdr_mem;
     273                 :         568 :           GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem);
     274         [ -  + ]:         568 :           if (unlikely (ehdr == NULL))
     275                 :           0 :             return 1;
     276   [ +  +  +  +  :         568 :           entsize = SH_ENTSIZE_HASH (ehdr);
                   +  + ]
     277                 :             :         }
     278                 :             :       else
     279                 :             :         {
     280   [ +  +  +  + ]:     2149793 :           Elf_Type t = shtype_map[TYPEIDX (type)];
     281         [ +  + ]:     2149793 :           if (t == ELF_T_NHDR && align == 8)
     282                 :         804 :             t = ELF_T_NHDR8;
     283   [ +  +  +  + ]:     2149793 :           if (t == ELF_T_VDEF || t == ELF_T_NHDR || t == ELF_T_NHDR8
     284   [ +  +  +  + ]:     2144986 :               || (t == ELF_T_GNUHASH && elf->class == ELFCLASS64))
     285                 :             :             entsize = 1;
     286                 :             :           else
     287                 :     2144506 :             entsize = __libelf_type_sizes[elf->class - 1][t];
     288                 :             :         }
     289                 :             : 
     290                 :             :       /* We assume it is an array of bytes if it is none of the structured
     291                 :             :          sections we know of.  */
     292                 :     2145074 :       if (entsize == 0)
     293                 :     2152993 :         entsize = 1;
     294                 :             : 
     295         [ -  + ]:     2152993 :       if (unlikely (size % entsize != 0))
     296                 :             :         {
     297                 :           0 :           __libelf_seterrno (ELF_E_INVALID_DATA);
     298                 :           0 :           return 1;
     299                 :             :         }
     300                 :             : 
     301                 :             :       /* We can use the mapped or loaded data if available.  */
     302         [ +  + ]:     2152993 :       if (elf->map_address != NULL)
     303                 :             :         {
     304                 :             :           /* First see whether the information in the section header is
     305                 :             :              valid and it does not ask for too much.  Check for unsigned
     306                 :             :              overflow.  */
     307   [ +  -  -  + ]:      688429 :           if (unlikely (offset > elf->maximum_size
     308                 :             :               || elf->maximum_size - offset < size))
     309                 :             :             {
     310                 :             :               /* Something is wrong.  */
     311                 :           0 :               __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
     312                 :           0 :               return 1;
     313                 :             :             }
     314                 :             : 
     315                 :      688429 :           scn->rawdata_base = scn->rawdata.d.d_buf
     316                 :      688429 :             = (char *) elf->map_address + elf->start_offset + offset;
     317                 :             :         }
     318         [ +  - ]:     1464564 :       else if (likely (elf->fildes != -1))
     319                 :             :         {
     320                 :             :           /* First see whether the information in the section header is
     321                 :             :              valid and it does not ask for too much.  Check for unsigned
     322                 :             :              overflow.  */
     323   [ +  -  -  + ]:     1464564 :           if (unlikely (offset > elf->maximum_size
     324                 :             :                         || elf->maximum_size - offset < size))
     325                 :             :             {
     326                 :             :               /* Something is wrong.  */
     327                 :           0 :               __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
     328                 :           0 :               return 1;
     329                 :             :             }
     330                 :             : 
     331                 :             :           /* We have to read the data from the file.  Allocate the needed
     332                 :             :              memory.  */
     333                 :     1464564 :           scn->rawdata_base = scn->rawdata.d.d_buf = malloc (size);
     334         [ -  + ]:     1464564 :           if (scn->rawdata.d.d_buf == NULL)
     335                 :             :             {
     336                 :           0 :               __libelf_seterrno (ELF_E_NOMEM);
     337                 :           0 :               return 1;
     338                 :             :             }
     339                 :             : 
     340                 :     2929128 :           ssize_t n = pread_retry (elf->fildes, scn->rawdata.d.d_buf, size,
     341                 :     1464564 :                                    elf->start_offset + offset);
     342         [ -  + ]:     1464564 :           if (unlikely ((size_t) n != size))
     343                 :             :             {
     344                 :             :               /* Cannot read the data.  */
     345                 :           0 :               free (scn->rawdata.d.d_buf);
     346                 :           0 :               scn->rawdata_base = scn->rawdata.d.d_buf = NULL;
     347                 :           0 :               __libelf_seterrno (ELF_E_READ_ERROR);
     348                 :           0 :               return 1;
     349                 :             :             }
     350                 :             :         }
     351                 :             :       else
     352                 :             :         {
     353                 :             :           /* The file descriptor is already closed, we cannot get the data
     354                 :             :              anymore.  */
     355                 :           0 :           __libelf_seterrno (ELF_E_FD_DISABLED);
     356                 :           0 :           return 1;
     357                 :             :         }
     358                 :             :     }
     359                 :             : 
     360                 :     2157301 :   scn->rawdata.d.d_size = size;
     361                 :             : 
     362                 :             :   /* Compressed data always has type ELF_T_CHDR regardless of the
     363                 :             :      section type.  */
     364         [ +  + ]:     2157301 :   if ((flags & SHF_COMPRESSED) != 0)
     365                 :        2632 :     scn->rawdata.d.d_type = ELF_T_CHDR;
     366                 :             :   else
     367                 :             :     {
     368                 :     2154669 :       GElf_Ehdr ehdr_mem;
     369                 :     2154669 :       GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem);
     370         [ -  + ]:     2154669 :       if (unlikely (ehdr == NULL))
     371                 :           0 :         return 1;
     372                 :     2154669 :       scn->rawdata.d.d_type = __libelf_data_type (ehdr, type, align);
     373                 :             :     }
     374                 :     2157301 :   scn->rawdata.d.d_off = 0;
     375                 :             : 
     376                 :             :   /* Make sure the alignment makes sense.  d_align should be aligned both
     377                 :             :      in the section (trivially true since d_off is zero) and in the file.
     378                 :             :      Unfortunately we cannot be too strict because there are ELF files
     379                 :             :      out there that fail this requirement.  We will try to fix those up
     380                 :             :      in elf_update when writing out the image.  But for very large
     381                 :             :      alignment values this can bloat the image considerably.  So here
     382                 :             :      just check and clamp the alignment value to not be bigger than the
     383                 :             :      actual offset of the data in the file.  Given that there is always
     384                 :             :      at least an ehdr this will only trigger for alignment values > 64
     385                 :             :      which should be uncommon.  */
     386                 :     2157301 :   align = align ?: 1;
     387         [ +  + ]:     2157301 :   if (type != SHT_NOBITS && align > offset)
     388                 :             :     {
     389                 :             :       /* Align the offset to the next power of two. Uses algorithm from
     390                 :             :          https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 */
     391                 :           2 :       align = offset - 1;
     392                 :           2 :       align |= align >> 1;
     393                 :           2 :       align |= align >> 2;
     394                 :           2 :       align |= align >> 4;
     395                 :           2 :       align |= align >> 8;
     396                 :           2 :       align |= align >> 16;
     397                 :           2 :       align |= align >> 32;
     398                 :           2 :       align++;
     399                 :             :     }
     400                 :     2157301 :   scn->rawdata.d.d_align = align;
     401                 :     2157301 :   if (elf->class == ELFCLASS32
     402                 :             :       || (offsetof (struct Elf, state.elf32.ehdr)
     403                 :             :           == offsetof (struct Elf, state.elf64.ehdr)))
     404                 :     2157301 :     scn->rawdata.d.d_version =
     405                 :     2157301 :       elf->state.elf32.ehdr->e_ident[EI_VERSION];
     406                 :             :   else
     407                 :             :     scn->rawdata.d.d_version =
     408                 :             :       elf->state.elf64.ehdr->e_ident[EI_VERSION];
     409                 :             : 
     410                 :     2157301 :   scn->rawdata.s = scn;
     411                 :             : 
     412                 :     2157301 :   scn->data_read = 1;
     413                 :             : 
     414                 :             :   /* We actually read data from the file.  At least we tried.  */
     415                 :     2157301 :   scn->flags |= ELF_F_FILEDATA;
     416                 :             : 
     417                 :     2157301 :   return 0;
     418                 :             : }
     419                 :             : 
     420                 :             : int
     421                 :             : internal_function
     422                 :       94070 : __libelf_set_rawdata (Elf_Scn *scn)
     423                 :             : {
     424                 :       94070 :   int result;
     425                 :             : 
     426         [ +  - ]:       94070 :   if (scn == NULL)
     427                 :             :     return 1;
     428                 :             : 
     429                 :       94070 :   rwlock_wrlock (scn->elf->lock);
     430                 :       94070 :   result = __libelf_set_rawdata_wrlock (scn);
     431                 :       94070 :   rwlock_unlock (scn->elf->lock);
     432                 :             : 
     433                 :       94070 :   return result;
     434                 :             : }
     435                 :             : 
     436                 :             : void
     437                 :             : internal_function
     438                 :     1536624 : __libelf_set_data_list_rdlock (Elf_Scn *scn, int wrlocked)
     439                 :             : {
     440   [ +  +  +  + ]:     1536624 :   if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0)
     441                 :     1532514 :     {
     442                 :     1532514 :       Elf *elf = scn->elf;
     443                 :             : 
     444                 :             :       /* Upgrade the lock to a write lock if necessary and check
     445                 :             :          nobody else already did the work.  */
     446         [ +  + ]:     1532514 :       if (!wrlocked)
     447                 :             :         {
     448                 :        1960 :           rwlock_unlock (elf->lock);
     449                 :        1960 :           rwlock_wrlock (elf->lock);
     450         [ +  - ]:        1960 :           if (scn->data_list_rear != NULL)
     451                 :             :             return;
     452                 :             :         }
     453                 :             : 
     454                 :             :       /* Convert according to the version and the type.   */
     455                 :     1532514 :       convert_data (scn, elf->class,
     456                 :             :                     (elf->class == ELFCLASS32
     457                 :             :                      || (offsetof (struct Elf, state.elf32.ehdr)
     458                 :             :                          == offsetof (struct Elf, state.elf64.ehdr))
     459                 :     1532514 :                      ? elf->state.elf32.ehdr->e_ident[EI_DATA]
     460                 :             :                      : elf->state.elf64.ehdr->e_ident[EI_DATA]),
     461                 :             :                     scn->rawdata.d.d_size, scn->rawdata.d.d_type);
     462                 :             :     }
     463                 :             :   else
     464                 :             :     {
     465                 :             :       /* This is an empty or NOBITS section.  There is no buffer but
     466                 :             :          the size information etc is important.  */
     467                 :        4110 :       scn->data_list.data.d = scn->rawdata.d;
     468                 :        4110 :       scn->data_list.data.s = scn;
     469                 :             :     }
     470                 :             : 
     471                 :     1536624 :   scn->data_list_rear = &scn->data_list;
     472                 :             : }
     473                 :             : 
     474                 :             : Elf_Data *
     475                 :             : internal_function
     476                 :     2820458 : __elf_getdata_rdlock (Elf_Scn *scn, Elf_Data *data)
     477                 :             : {
     478                 :     2820458 :   Elf_Data *result = NULL;
     479                 :     2820458 :   Elf *elf;
     480                 :     2820458 :   int locked = 0;
     481                 :             : 
     482         [ -  + ]:     2820458 :   if (scn == NULL)
     483                 :             :     return NULL;
     484                 :             : 
     485         [ -  + ]:     2820458 :   if (unlikely (scn->elf->kind != ELF_K_ELF))
     486                 :             :     {
     487                 :           0 :       __libelf_seterrno (ELF_E_INVALID_HANDLE);
     488                 :           0 :       return NULL;
     489                 :             :     }
     490                 :             : 
     491                 :             :   /* We will need this multiple times later on.  */
     492                 :     2820458 :   elf = scn->elf;
     493                 :             : 
     494                 :             :   /* If `data' is not NULL this means we are not addressing the initial
     495                 :             :      data in the file.  But this also means this data is already read
     496                 :             :      (since otherwise it is not possible to have a valid `data' pointer)
     497                 :             :      and all the data structures are initialized as well.  In this case
     498                 :             :      we can simply walk the list of data records.  */
     499         [ +  + ]:     2820458 :   if (data != NULL)
     500                 :             :     {
     501                 :     1054798 :       Elf_Data_List *runp;
     502                 :             : 
     503                 :             :       /* It is not possible that if DATA is not NULL the first entry is
     504                 :             :          returned.  But this also means that there must be a first data
     505                 :             :          entry.  */
     506         [ +  + ]:     1054798 :       if (scn->data_list_rear == NULL
     507                 :             :           /* The section the reference data is for must match the section
     508                 :             :              parameter.  */
     509         [ -  + ]:     1054700 :           || unlikely (((Elf_Data_Scn *) data)->s != scn))
     510                 :             :         {
     511                 :          98 :           __libelf_seterrno (ELF_E_DATA_MISMATCH);
     512                 :          98 :           goto out;
     513                 :             :         }
     514                 :             : 
     515                 :             :       /* We start searching with the first entry.  */
     516                 :     1054700 :       runp = &scn->data_list;
     517                 :             : 
     518                 :     1054888 :       while (1)
     519                 :             :         {
     520                 :             :           /* If `data' does not match any known record punt.  */
     521         [ +  + ]:     1054794 :           if (runp == NULL)
     522                 :             :             {
     523                 :           6 :               __libelf_seterrno (ELF_E_DATA_MISMATCH);
     524                 :           6 :               goto out;
     525                 :             :             }
     526                 :             : 
     527         [ +  + ]:     1054788 :           if (&runp->data.d == data)
     528                 :             :             /* Found the entry.  */
     529                 :             :             break;
     530                 :             : 
     531                 :          94 :           runp = runp->next;
     532                 :             :         }
     533                 :             : 
     534                 :             :       /* Return the data for the next data record.  */
     535         [ +  + ]:     1054694 :       result = runp->next ? &runp->next->data.d : NULL;
     536                 :     1054694 :       goto out;
     537                 :             :     }
     538                 :             : 
     539                 :             :   /* If the data for this section was not yet initialized do it now.  */
     540         [ +  + ]:     1765660 :   if (scn->data_read == 0)
     541                 :             :     {
     542                 :             :       /* We cannot acquire a write lock while we are holding a read
     543                 :             :          lock.  Therefore give up the read lock and then get the write
     544                 :             :          lock.  But this means that the data could meanwhile be
     545                 :             :          modified, therefore start the tests again.  */
     546                 :     1530230 :       rwlock_unlock (elf->lock);
     547                 :     1530230 :       rwlock_wrlock (elf->lock);
     548                 :     1530230 :       locked = 1;
     549                 :             : 
     550                 :             :       /* Read the data from the file.  There is always a file (or
     551                 :             :          memory region) associated with this descriptor since
     552                 :             :          otherwise the `data_read' flag would be set.  */
     553         [ -  + ]:     1530230 :       if (scn->data_read == 0 && __libelf_set_rawdata_wrlock (scn) != 0)
     554                 :             :         /* Something went wrong.  The error value is already set.  */
     555                 :           0 :         goto out;
     556                 :             :     }
     557                 :             : 
     558                 :             :   /* At this point we know the raw data is available.  But it might be
     559                 :             :      empty in case the section has size zero (for whatever reason).
     560                 :             :      Now create the converted data in case this is necessary.  */
     561         [ +  + ]:     1765660 :   if (scn->data_list_rear == NULL)
     562                 :     1532248 :     __libelf_set_data_list_rdlock (scn, locked);
     563                 :             : 
     564                 :             :   /* Return the first data element in the list.  */
     565                 :     1765660 :   result = &scn->data_list.data.d;
     566                 :             : 
     567                 :             :  out:
     568                 :             :   return result;
     569                 :             : }
     570                 :             : 
     571                 :             : Elf_Data *
     572                 :     2820308 : elf_getdata (Elf_Scn *scn, Elf_Data *data)
     573                 :             : {
     574                 :     2820308 :   Elf_Data *result;
     575                 :             : 
     576         [ +  + ]:     2820308 :   if (scn == NULL)
     577                 :             :     return NULL;
     578                 :             : 
     579                 :     2820092 :   rwlock_rdlock (scn->elf->lock);
     580                 :     2820092 :   result = __elf_getdata_rdlock (scn, data);
     581                 :     2820092 :   rwlock_unlock (scn->elf->lock);
     582                 :             : 
     583                 :     2820092 :   return result;
     584                 :             : }
     585                 :             : 
     586                 :             : Elf_Data *
     587                 :             : internal_function
     588                 :          18 : __elf_getdata_wrlock (Elf_Scn *scn, Elf_Data *data)
     589                 :             : {
     590                 :          18 :   Elf_Data *result;
     591                 :             : 
     592         [ +  - ]:          18 :   if (scn == NULL)
     593                 :             :     return NULL;
     594                 :             : 
     595                 :          18 :   result = __elf_getdata_rdlock (scn, data);
     596                 :             : 
     597                 :          18 :   return result;
     598                 :             : }
     599                 :             : INTDEF(elf_getdata)
        

Generated by: LCOV version 2.0-1