LCOV - code coverage report
Current view: top level - elfutils/libdwfl - dwfl_module_build_id.c (source / functions) Hit Total Coverage
Test: lcov.out Lines: 51 58 87.9 %
Date: 2012-10-31 Functions: 4 4 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 39 56 69.6 %

           Branch data     Line data    Source code
       1                 :            : /* Return build ID information for a module.
       2                 :            :    Copyright (C) 2007-2010 Red Hat, Inc.
       3                 :            :    This file is part of elfutils.
       4                 :            : 
       5                 :            :    This file is free software; you can redistribute it and/or modify
       6                 :            :    it under the terms of either
       7                 :            : 
       8                 :            :      * the GNU Lesser General Public License as published by the Free
       9                 :            :        Software Foundation; either version 3 of the License, or (at
      10                 :            :        your option) any later version
      11                 :            : 
      12                 :            :    or
      13                 :            : 
      14                 :            :      * the GNU General Public License as published by the Free
      15                 :            :        Software Foundation; either version 2 of the License, or (at
      16                 :            :        your option) any later version
      17                 :            : 
      18                 :            :    or both in parallel, as here.
      19                 :            : 
      20                 :            :    elfutils is distributed in the hope that it will be useful, but
      21                 :            :    WITHOUT ANY WARRANTY; without even the implied warranty of
      22                 :            :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      23                 :            :    General Public License for more details.
      24                 :            : 
      25                 :            :    You should have received copies of the GNU General Public License and
      26                 :            :    the GNU Lesser General Public License along with this program.  If
      27                 :            :    not, see <http://www.gnu.org/licenses/>.  */
      28                 :            : 
      29                 :            : #include "libdwflP.h"
      30                 :            : 
      31                 :            : static int
      32                 :         62 : found_build_id (Dwfl_Module *mod, bool set,
      33                 :            :                 const void *bits, int len, GElf_Addr vaddr)
      34                 :            : {
      35         [ +  + ]:         62 :   if (!set)
      36                 :            :     /* When checking bits, we do not compare VADDR because the
      37                 :            :        address found in a debuginfo file may not match the main
      38                 :            :        file as modified by prelink.  */
      39                 :         33 :     return 1 + (mod->build_id_len == len
      40 [ +  - ][ +  + ]:         33 :                 && !memcmp (bits, mod->build_id_bits, len));
      41                 :            : 
      42                 :         29 :   void *copy = malloc (len);
      43         [ -  + ]:         29 :   if (unlikely (copy == NULL))
      44                 :            :     {
      45                 :          0 :       __libdwfl_seterrno (DWFL_E_NOMEM);
      46                 :          0 :       return -1;
      47                 :            :     }
      48                 :            : 
      49                 :         29 :   mod->build_id_bits = memcpy (copy, bits, len);
      50                 :         29 :   mod->build_id_vaddr = vaddr;
      51                 :         29 :   mod->build_id_len = len;
      52                 :         62 :   return len;
      53                 :            : }
      54                 :            : 
      55                 :            : #define NO_VADDR        ((GElf_Addr) -1l)
      56                 :            : 
      57                 :            : static int
      58                 :         80 : check_notes (Dwfl_Module *mod, bool set, Elf_Data *data, GElf_Addr data_vaddr)
      59                 :            : {
      60                 :         80 :   size_t pos = 0;
      61                 :            :   GElf_Nhdr nhdr;
      62                 :            :   size_t name_pos;
      63                 :            :   size_t desc_pos;
      64         [ +  + ]:        164 :   while ((pos = gelf_getnote (data, pos, &nhdr, &name_pos, &desc_pos)) > 0)
      65         [ +  + ]:         84 :     if (nhdr.n_type == NT_GNU_BUILD_ID
      66 [ +  - ][ +  - ]:         62 :         && nhdr.n_namesz == sizeof "GNU" && !memcmp (data->d_buf + name_pos,
      67                 :            :                                                      "GNU", sizeof "GNU"))
      68         [ +  - ]:         84 :       return found_build_id (mod, set,
      69                 :         62 :                              data->d_buf + desc_pos, nhdr.n_descsz,
      70                 :            :                              data_vaddr == NO_VADDR ? 0
      71                 :         62 :                              : data_vaddr + desc_pos);
      72                 :            :   return 0;
      73                 :            : }
      74                 :            : 
      75                 :            : int
      76                 :            : internal_function
      77                 :         70 : __libdwfl_find_build_id (Dwfl_Module *mod, bool set, Elf *elf)
      78                 :            : {
      79                 :         70 :   size_t shstrndx = SHN_UNDEF;
      80                 :         70 :   int result = 0;
      81                 :            : 
      82                 :         70 :   Elf_Scn *scn = elf_nextscn (elf, NULL);
      83                 :            : 
      84         [ +  + ]:         70 :   if (scn == NULL)
      85                 :            :     {
      86                 :            :       /* No sections, have to look for phdrs.  */
      87                 :            :       GElf_Ehdr ehdr_mem;
      88                 :          4 :       GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
      89                 :            :       size_t phnum;
      90         [ +  - ]:          4 :       if (unlikely (ehdr == NULL)
      91         [ +  - ]:          4 :           || unlikely (elf_getphdrnum (elf, &phnum) != 0))
      92                 :            :         {
      93                 :          0 :           __libdwfl_seterrno (DWFL_E_LIBELF);
      94                 :            :           return -1;
      95                 :            :         }
      96 [ +  + ][ +  - ]:         86 :       for (size_t i = 0; result == 0 && i < phnum; ++i)
      97                 :            :         {
      98                 :            :           GElf_Phdr phdr_mem;
      99                 :         16 :           GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
     100 [ +  - ][ +  + ]:         16 :           if (likely (phdr != NULL) && phdr->p_type == PT_NOTE)
     101                 :          4 :             result = check_notes (mod, set,
     102                 :            :                                   elf_getdata_rawchunk (elf,
     103                 :          4 :                                                         phdr->p_offset,
     104                 :            :                                                         phdr->p_filesz,
     105                 :            :                                                         ELF_T_NHDR),
     106                 :            :                                   dwfl_adjusted_address (mod, phdr->p_vaddr));
     107                 :            :         }
     108                 :            :     }
     109                 :            :   else
     110                 :            :     do
     111                 :            :       {
     112                 :            :         GElf_Shdr shdr_mem;
     113                 :        178 :         GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
     114 [ +  - ][ +  + ]:        178 :         if (likely (shdr != NULL) && shdr->sh_type == SHT_NOTE)
     115                 :            :           {
     116                 :            :             /* Determine the right sh_addr in this module.  */
     117                 :         76 :             GElf_Addr vaddr = 0;
     118         [ -  + ]:         76 :             if (!(shdr->sh_flags & SHF_ALLOC))
     119                 :          0 :               vaddr = NO_VADDR;
     120         [ +  - ]:         76 :             else if (mod->e_type != ET_REL)
     121                 :         76 :               vaddr = dwfl_adjusted_address (mod, shdr->sh_addr);
     122         [ #  # ]:          0 :             else if (__libdwfl_relocate_value (mod, elf, &shstrndx,
     123                 :          0 :                                                elf_ndxscn (scn), &vaddr))
     124                 :          0 :               vaddr = NO_VADDR;
     125                 :         76 :             result = check_notes (mod, set, elf_getdata (scn, NULL), vaddr);
     126                 :            :           }
     127                 :            :       }
     128 [ +  + ][ +  + ]:        182 :     while (result == 0 && (scn = elf_nextscn (elf, scn)) != NULL);
     129                 :            : 
     130                 :            :   return result;
     131                 :            : }
     132                 :            : 
     133                 :            : int
     134                 :         96 : dwfl_module_build_id (Dwfl_Module *mod,
     135                 :            :                       const unsigned char **bits, GElf_Addr *vaddr)
     136                 :            : {
     137         [ +  - ]:         96 :   if (mod == NULL)
     138                 :            :     return -1;
     139                 :            : 
     140 [ +  + ][ +  - ]:         96 :   if (mod->build_id_len == 0 && mod->main.elf != NULL)
     141                 :            :     {
     142                 :            :       /* We have the file, but have not examined it yet.  */
     143                 :         37 :       int result = __libdwfl_find_build_id (mod, true, mod->main.elf);
     144         [ +  + ]:         37 :       if (result <= 0)
     145                 :            :         {
     146                 :          8 :           mod->build_id_len = -1;    /* Cache negative result.  */
     147                 :          8 :           return result;
     148                 :            :         }
     149                 :            :     }
     150                 :            : 
     151         [ +  - ]:         88 :   if (mod->build_id_len <= 0)
     152                 :            :     return 0;
     153                 :            : 
     154                 :         88 :   *bits = mod->build_id_bits;
     155                 :         88 :   *vaddr = mod->build_id_vaddr;
     156                 :         96 :   return mod->build_id_len;
     157                 :            : }
     158                 :            : INTDEF (dwfl_module_build_id)
     159                 :         80 : NEW_VERSION (dwfl_module_build_id, ELFUTILS_0.138)
     160                 :            : 
     161                 :            : #ifdef SHARED
     162                 :            : COMPAT_VERSION (dwfl_module_build_id, ELFUTILS_0.130, vaddr_at_end)
     163                 :            : 
     164                 :            : int
     165                 :            : _compat_vaddr_at_end_dwfl_module_build_id (Dwfl_Module *mod,
     166                 :            :                                            const unsigned char **bits,
     167                 :            :                                            GElf_Addr *vaddr)
     168                 :            : {
     169                 :            :   int result = INTUSE(dwfl_module_build_id) (mod, bits, vaddr);
     170                 :            :   if (result > 0)
     171                 :            :     *vaddr += (result + 3) & -4;
     172                 :            :   return result;
     173                 :            : }
     174                 :            : #endif

Generated by: LCOV version 1.9