LCOV - code coverage report
Current view: top level - libelf - elf_getdata.c (source / functions) Hit Total Coverage
Test: elfutils-0.175 Lines: 131 157 83.4 %
Date: 2018-11-16 13:02:39 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13