LCOV - code coverage report
Current view: top level - libdw - dwarf_ranges.c (source / functions) Hit Total Coverage
Test: elfutils-0.191 Lines: 211 331 63.7 %
Date: 2024-08-30 13:26:44 Functions: 3 3 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 117 226 51.8 %

           Branch data     Line data    Source code
       1                 :            : /* Enumerate the PC ranges covered by a DIE.
       2                 :            :    Copyright (C) 2005, 2007, 2009, 2018 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                 :            : #ifdef HAVE_CONFIG_H
      30                 :            : # include <config.h>
      31                 :            : #endif
      32                 :            : 
      33                 :            : #include "libdwP.h"
      34                 :            : #include <dwarf.h>
      35                 :            : #include <assert.h>
      36                 :            : 
      37                 :            : /* Read up begin/end pair and increment read pointer.
      38                 :            :     - If it's normal range record, set up `*beginp' and `*endp' and return 0.
      39                 :            :     - If it's a default location, set `*beginp' (0), `*endp' (-1) and return 0.
      40                 :            :     - If it's base address selection record, set up `*basep' and return 1.
      41                 :            :     - If it's end of rangelist, don't set anything and return 2
      42                 :            :     - If an error occurs, don't set anything and return -1.  */
      43                 :            : internal_function int
      44                 :    4096186 : __libdw_read_begin_end_pair_inc (Dwarf_CU *cu, int sec_index,
      45                 :            :                                  const unsigned char **addrp,
      46                 :            :                                  const unsigned char *addrend,
      47                 :            :                                  int width,
      48                 :            :                                  Dwarf_Addr *beginp, Dwarf_Addr *endp,
      49                 :            :                                  Dwarf_Addr *basep)
      50                 :            : {
      51                 :    4096186 :   Dwarf *dbg = cu->dbg;
      52         [ +  + ]:    4096186 :   if (sec_index == IDX_debug_loc
      53         [ +  - ]:        920 :       && cu->version < 5
      54         [ +  + ]:        920 :       && cu->unit_type == DW_UT_split_compile)
      55                 :            :     {
      56                 :            :       /* GNU DebugFission.  */
      57                 :        624 :       const unsigned char *addr = *addrp;
      58         [ -  + ]:        624 :       if (addrend - addr < 1)
      59                 :          0 :         goto invalid;
      60                 :            : 
      61                 :        624 :       const char code = *addr++;
      62                 :        624 :       uint64_t begin = 0, end = 0, base = *basep, addr_idx;
      63   [ +  -  -  +  :        624 :       switch (code)
                      - ]
      64                 :            :         {
      65                 :         46 :         case DW_LLE_GNU_end_of_list_entry:
      66                 :         46 :           *addrp = addr;
      67                 :        624 :           return 2;
      68                 :            : 
      69                 :          0 :         case DW_LLE_GNU_base_address_selection_entry:
      70         [ #  # ]:          0 :           if (addrend - addr < 1)
      71                 :          0 :             goto invalid;
      72                 :          0 :           get_uleb128 (addr_idx, addr, addrend);
      73         [ #  # ]:          0 :           if (__libdw_addrx (cu, addr_idx, &base) != 0)
      74                 :            :             return -1;
      75                 :          0 :           *basep = base;
      76                 :          0 :           *addrp = addr;
      77                 :          0 :           return 1;
      78                 :            : 
      79                 :          0 :         case DW_LLE_GNU_start_end_entry:
      80         [ #  # ]:          0 :           if (addrend - addr < 1)
      81                 :          0 :             goto invalid;
      82                 :          0 :           get_uleb128 (addr_idx, addr, addrend);
      83         [ #  # ]:          0 :           if (__libdw_addrx (cu, addr_idx, &begin) != 0)
      84                 :            :             return -1;
      85         [ #  # ]:          0 :           if (addrend - addr < 1)
      86                 :          0 :             goto invalid;
      87                 :          0 :           get_uleb128 (addr_idx, addr, addrend);
      88         [ #  # ]:          0 :           if (__libdw_addrx (cu, addr_idx, &end) != 0)
      89                 :            :             return -1;
      90                 :            : 
      91                 :          0 :           *beginp = begin;
      92                 :          0 :           *endp = end;
      93                 :          0 :           *addrp = addr;
      94                 :          0 :           return 0;
      95                 :            : 
      96                 :        578 :         case DW_LLE_GNU_start_length_entry:
      97         [ -  + ]:        578 :           if (addrend - addr < 1)
      98                 :          0 :             goto invalid;
      99                 :        578 :           get_uleb128 (addr_idx, addr, addrend);
     100         [ -  + ]:        578 :           if (__libdw_addrx (cu, addr_idx, &begin) != 0)
     101                 :            :             return -1;
     102         [ -  + ]:        578 :           if (addrend - addr < 4)
     103                 :          0 :             goto invalid;
     104         [ -  + ]:        578 :           end = read_4ubyte_unaligned_inc (dbg, addr);
     105                 :            : 
     106                 :        578 :           *beginp = begin;
     107                 :        578 :           *endp = begin + end;
     108                 :        578 :           *addrp = addr;
     109                 :        578 :           return 0;
     110                 :            : 
     111                 :          0 :         default:
     112                 :          0 :           goto invalid;
     113                 :            :         }
     114                 :            :     }
     115         [ +  + ]:    4095562 :   else if (sec_index == IDX_debug_ranges || sec_index == IDX_debug_loc)
     116                 :            :     {
     117                 :        976 :       Dwarf_Addr escape = (width == 8 ? (Elf64_Addr) -1
     118         [ -  + ]:        488 :                            : (Elf64_Addr) (Elf32_Addr) -1);
     119                 :        488 :       Dwarf_Addr begin;
     120                 :        488 :       Dwarf_Addr end;
     121                 :            : 
     122                 :        488 :       const unsigned char *addr = *addrp;
     123         [ -  + ]:        488 :       if (addrend - addr < width * 2)
     124                 :            :         {
     125                 :          0 :         invalid:
     126                 :          0 :           __libdw_seterrno (DWARF_E_INVALID_DWARF);
     127                 :          0 :           return -1;
     128                 :            :         }
     129                 :            : 
     130   [ -  +  -  +  :        488 :       bool begin_relocated = READ_AND_RELOCATE (__libdw_relocate_address,
             -  -  -  + ]
     131                 :            :                                                 begin);
     132   [ -  +  -  +  :        488 :       bool end_relocated = READ_AND_RELOCATE (__libdw_relocate_address,
             -  -  -  + ]
     133                 :            :                                               end);
     134                 :        488 :       *addrp = addr;
     135                 :            : 
     136                 :            :       /* Unrelocated escape for begin means base address selection.  */
     137         [ +  + ]:        488 :       if (begin == escape && !begin_relocated)
     138                 :            :         {
     139         [ -  + ]:          2 :           if (unlikely (end == escape))
     140                 :          0 :             goto invalid;
     141                 :            : 
     142                 :          2 :           *basep = end;
     143                 :          2 :           return 1;
     144                 :            :         }
     145                 :            : 
     146                 :            :       /* Unrelocated pair of zeroes means end of range list.  */
     147   [ +  +  +  + ]:        486 :       if (begin == 0 && end == 0 && !begin_relocated && !end_relocated)
     148                 :            :         return 2;
     149                 :            : 
     150                 :            :       /* Don't check for begin_relocated == end_relocated.  Serve the data
     151                 :            :          to the client even though it may be buggy.  */
     152                 :        420 :       *beginp = begin + *basep;
     153                 :        420 :       *endp = end + *basep;
     154                 :            : 
     155                 :        420 :       return 0;
     156                 :            :     }
     157         [ +  + ]:    4095074 :   else if (sec_index == IDX_debug_rnglists)
     158                 :            :     {
     159                 :      16634 :       const unsigned char *addr = *addrp;
     160         [ -  + ]:      16634 :       if (addrend - addr < 1)
     161                 :          0 :         goto invalid;
     162                 :            : 
     163                 :      16634 :       const char code = *addr++;
     164                 :      16634 :       uint64_t begin = 0, end = 0, base = *basep, addr_idx;
     165   [ +  +  -  +  :      16634 :       switch (code)
             +  +  -  +  
                      - ]
     166                 :            :         {
     167                 :         38 :         case DW_RLE_end_of_list:
     168                 :         38 :           *addrp = addr;
     169                 :      16634 :           return 2;
     170                 :            : 
     171                 :         20 :         case DW_RLE_base_addressx:
     172         [ -  + ]:         20 :           if (addrend - addr < 1)
     173                 :          0 :             goto invalid;
     174                 :         20 :           get_uleb128 (addr_idx, addr, addrend);
     175         [ -  + ]:         20 :           if (__libdw_addrx (cu, addr_idx, &base) != 0)
     176                 :            :             return -1;
     177                 :            : 
     178                 :         20 :           *basep = base;
     179                 :         20 :           *addrp = addr;
     180                 :         20 :           return 1;
     181                 :            : 
     182                 :          0 :         case DW_RLE_startx_endx:
     183         [ #  # ]:          0 :           if (addrend - addr < 1)
     184                 :          0 :             goto invalid;
     185                 :          0 :           get_uleb128 (addr_idx, addr, addrend);
     186         [ #  # ]:          0 :           if (__libdw_addrx (cu, addr_idx, &begin) != 0)
     187                 :            :             return -1;
     188         [ #  # ]:          0 :           if (addrend - addr < 1)
     189                 :          0 :             goto invalid;
     190                 :          0 :           get_uleb128 (addr_idx, addr, addrend);
     191         [ #  # ]:          0 :           if (__libdw_addrx (cu, addr_idx, &end) != 0)
     192                 :            :             return -1;
     193                 :            : 
     194                 :          0 :           *beginp = begin;
     195                 :          0 :           *endp = end;
     196                 :          0 :           *addrp = addr;
     197                 :          0 :           return 0;
     198                 :            : 
     199                 :          4 :         case DW_RLE_startx_length:
     200         [ -  + ]:          4 :           if (addrend - addr < 1)
     201                 :          0 :             goto invalid;
     202                 :          4 :           get_uleb128 (addr_idx, addr, addrend);
     203         [ -  + ]:          4 :           if (__libdw_addrx (cu, addr_idx, &begin) != 0)
     204                 :            :             return -1;
     205         [ -  + ]:          4 :           if (addrend - addr < 1)
     206                 :          0 :             goto invalid;
     207                 :          4 :           get_uleb128 (end, addr, addrend);
     208                 :            : 
     209                 :          4 :           *beginp = begin;
     210                 :          4 :           *endp = begin + end;
     211                 :          4 :           *addrp = addr;
     212                 :          4 :           return 0;
     213                 :            : 
     214                 :      13716 :         case DW_RLE_offset_pair:
     215         [ -  + ]:      13716 :           if (addrend - addr < 1)
     216                 :          0 :             goto invalid;
     217                 :      13716 :           get_uleb128 (begin, addr, addrend);
     218         [ -  + ]:      13716 :           if (addrend - addr < 1)
     219                 :          0 :             goto invalid;
     220                 :      13716 :           get_uleb128 (end, addr, addrend);
     221                 :            : 
     222                 :      13716 :           *beginp = begin + base;
     223                 :      13716 :           *endp = end + base;
     224                 :      13716 :           *addrp = addr;
     225                 :      13716 :           return 0;
     226                 :            : 
     227                 :       2702 :         case DW_RLE_base_address:
     228         [ -  + ]:       2702 :           if (addrend - addr < width)
     229                 :          0 :             goto invalid;
     230                 :       2702 :           __libdw_read_address_inc (dbg, sec_index, &addr, width, &base);
     231                 :            : 
     232                 :       2702 :           *basep = base;
     233                 :       2702 :           *addrp = addr;
     234                 :       2702 :           return 1;
     235                 :            : 
     236                 :          0 :         case DW_RLE_start_end:
     237         [ #  # ]:          0 :           if (addrend - addr < 2 * width)
     238                 :          0 :             goto invalid;
     239                 :          0 :           __libdw_read_address_inc (dbg, sec_index, &addr, width, &begin);
     240                 :          0 :           __libdw_read_address_inc (dbg, sec_index, &addr, width, &end);
     241                 :            : 
     242                 :          0 :           *beginp = begin;
     243                 :          0 :           *endp = end;
     244                 :          0 :           *addrp = addr;
     245                 :          0 :           return 0;
     246                 :            : 
     247                 :        154 :         case DW_RLE_start_length:
     248         [ -  + ]:        154 :           if (addrend - addr < width)
     249                 :          0 :             goto invalid;
     250                 :        154 :           __libdw_read_address_inc (dbg, sec_index, &addr, width, &begin);
     251         [ -  + ]:        154 :           if (addrend - addr < 1)
     252                 :          0 :             goto invalid;
     253                 :        154 :           get_uleb128 (end, addr, addrend);
     254                 :            : 
     255                 :        154 :           *beginp = begin;
     256                 :        154 :           *endp = begin + end;
     257                 :        154 :           *addrp = addr;
     258                 :        154 :           return 0;
     259                 :            : 
     260                 :          0 :         default:
     261                 :          0 :           goto invalid;
     262                 :            :         }
     263                 :            :     }
     264         [ +  - ]:    4078440 :   else if (sec_index == IDX_debug_loclists)
     265                 :            :     {
     266                 :    4078440 :       const unsigned char *addr = *addrp;
     267         [ -  + ]:    4078440 :       if (addrend - addr < 1)
     268                 :          0 :         goto invalid;
     269                 :            : 
     270                 :    4078440 :       const char code = *addr++;
     271                 :    4078440 :       uint64_t begin = 0, end = 0, base = *basep, addr_idx;
     272   [ +  -  -  +  :    4078440 :       switch (code)
          +  -  +  -  +  
                      - ]
     273                 :            :         {
     274                 :     129906 :         case DW_LLE_end_of_list:
     275                 :     129906 :           *addrp = addr;
     276                 :    4078440 :           return 2;
     277                 :            : 
     278                 :          0 :         case DW_LLE_base_addressx:
     279         [ #  # ]:          0 :           if (addrend - addr < 1)
     280                 :          0 :             goto invalid;
     281                 :          0 :           get_uleb128 (addr_idx, addr, addrend);
     282         [ #  # ]:          0 :           if (__libdw_addrx (cu, addr_idx, &base) != 0)
     283                 :            :             return -1;
     284                 :            : 
     285                 :          0 :           *basep = base;
     286                 :          0 :           *addrp = addr;
     287                 :          0 :           return 1;
     288                 :            : 
     289                 :          0 :         case DW_LLE_startx_endx:
     290         [ #  # ]:          0 :           if (addrend - addr < 1)
     291                 :          0 :             goto invalid;
     292                 :          0 :           get_uleb128 (addr_idx, addr, addrend);
     293         [ #  # ]:          0 :           if (__libdw_addrx (cu, addr_idx, &begin) != 0)
     294                 :            :             return -1;
     295         [ #  # ]:          0 :           if (addrend - addr < 1)
     296                 :          0 :             goto invalid;
     297                 :          0 :           get_uleb128 (addr_idx, addr, addrend);
     298         [ #  # ]:          0 :           if (__libdw_addrx (cu, addr_idx, &end) != 0)
     299                 :            :             return -1;
     300                 :            : 
     301                 :          0 :           *beginp = begin;
     302                 :          0 :           *endp = end;
     303                 :          0 :           *addrp = addr;
     304                 :          0 :           return 0;
     305                 :            : 
     306                 :        454 :         case DW_LLE_startx_length:
     307         [ -  + ]:        454 :           if (addrend - addr < 1)
     308                 :          0 :             goto invalid;
     309                 :        454 :           get_uleb128 (addr_idx, addr, addrend);
     310         [ -  + ]:        454 :           if (__libdw_addrx (cu, addr_idx, &begin) != 0)
     311                 :            :             return -1;
     312         [ -  + ]:        454 :           if (addrend - addr < 1)
     313                 :          0 :             goto invalid;
     314                 :        454 :           get_uleb128 (end, addr, addrend);
     315                 :            : 
     316                 :        454 :           *beginp = begin;
     317                 :        454 :           *endp = begin + end;
     318                 :        454 :           *addrp = addr;
     319                 :        454 :           return 0;
     320                 :            : 
     321                 :    3869742 :         case DW_LLE_offset_pair:
     322         [ -  + ]:    3869742 :           if (addrend - addr < 1)
     323                 :          0 :             goto invalid;
     324                 :    3869742 :           get_uleb128 (begin, addr, addrend);
     325         [ -  + ]:    3869742 :           if (addrend - addr < 1)
     326                 :          0 :             goto invalid;
     327                 :    3869742 :           get_uleb128 (end, addr, addrend);
     328                 :            : 
     329                 :    3869742 :           *beginp = begin + base;
     330                 :    3869742 :           *endp = end + base;
     331                 :    3869742 :           *addrp = addr;
     332                 :    3869742 :           return 0;
     333                 :            : 
     334                 :          0 :         case DW_LLE_default_location:
     335                 :          0 :           *beginp = 0;
     336                 :          0 :           *endp = (Dwarf_Addr) -1;
     337                 :          0 :           *addrp = addr;
     338                 :          0 :           return 0;
     339                 :            : 
     340                 :      61138 :         case DW_LLE_base_address:
     341         [ -  + ]:      61138 :           if (addrend - addr < width)
     342                 :          0 :             goto invalid;
     343                 :      61138 :           __libdw_read_address_inc (dbg, sec_index, &addr, width, &base);
     344                 :            : 
     345                 :      61138 :           *basep = base;
     346                 :      61138 :           *addrp = addr;
     347                 :      61138 :           return 1;
     348                 :            : 
     349                 :          0 :         case DW_LLE_start_end:
     350         [ #  # ]:          0 :           if (addrend - addr < 2 * width)
     351                 :          0 :             goto invalid;
     352                 :          0 :           __libdw_read_address_inc (dbg, sec_index, &addr, width, &begin);
     353                 :          0 :           __libdw_read_address_inc (dbg, sec_index, &addr, width, &end);
     354                 :            : 
     355                 :          0 :           *beginp = begin;
     356                 :          0 :           *endp = end;
     357                 :          0 :           *addrp = addr;
     358                 :          0 :           return 0;
     359                 :            : 
     360                 :      17200 :         case DW_LLE_start_length:
     361         [ -  + ]:      17200 :           if (addrend - addr < width)
     362                 :          0 :             goto invalid;
     363                 :      17200 :           __libdw_read_address_inc (dbg, sec_index, &addr, width, &begin);
     364         [ -  + ]:      17200 :           if (addrend - addr < 1)
     365                 :          0 :             goto invalid;
     366                 :      17200 :           get_uleb128 (end, addr, addrend);
     367                 :            : 
     368                 :      17200 :           *beginp = begin;
     369                 :      17200 :           *endp = begin + end;
     370                 :      17200 :           *addrp = addr;
     371                 :      17200 :           return 0;
     372                 :            : 
     373                 :          0 :         default:
     374                 :          0 :           goto invalid;
     375                 :            :         }
     376                 :            :     }
     377                 :            :   else
     378                 :            :     {
     379                 :          0 :       __libdw_seterrno (DWARF_E_INVALID_DWARF);
     380                 :          0 :       return -1;
     381                 :            :     }
     382                 :            : }
     383                 :            : 
     384                 :            : static int
     385                 :      13898 : initial_offset (Dwarf_Attribute *attr, ptrdiff_t *offset)
     386                 :            : {
     387                 :      27796 :   size_t secidx = (attr->cu->version < 5
     388         [ +  + ]:      13898 :                    ? IDX_debug_ranges : IDX_debug_rnglists);
     389                 :            : 
     390                 :      13898 :   Dwarf_Word start_offset;
     391         [ +  + ]:      13898 :   if (attr->form == DW_FORM_rnglistx)
     392                 :            :     {
     393                 :         40 :       Dwarf_Word idx;
     394                 :         40 :       Dwarf_CU *cu = attr->cu;
     395                 :         40 :       const unsigned char *datap = attr->valp;
     396                 :         40 :       const unsigned char *endp = cu->endp;
     397         [ -  + ]:         40 :       if (datap >= endp)
     398                 :            :         {
     399                 :          0 :           __libdw_seterrno (DWARF_E_INVALID_DWARF);
     400                 :          0 :           return -1;
     401                 :            :         }
     402                 :         40 :       get_uleb128 (idx, datap, endp);
     403                 :            : 
     404                 :         40 :       Elf_Data *data = cu->dbg->sectiondata[secidx];
     405   [ +  +  +  - ]:         40 :       if (data == NULL && cu->unit_type == DW_UT_split_compile)
     406                 :            :         {
     407                 :          8 :           cu = __libdw_find_split_unit (cu);
     408         [ +  - ]:          8 :           if (cu != NULL)
     409                 :          8 :             data = cu->dbg->sectiondata[secidx];
     410                 :            :         }
     411                 :            : 
     412         [ -  + ]:          8 :       if (data == NULL)
     413                 :            :         {
     414         [ #  # ]:          0 :           __libdw_seterrno (secidx == IDX_debug_ranges
     415                 :            :                             ? DWARF_E_NO_DEBUG_RANGES
     416                 :            :                             : DWARF_E_NO_DEBUG_RNGLISTS);
     417                 :          0 :           return -1;
     418                 :            :         }
     419                 :            : 
     420                 :         40 :       Dwarf_Off range_base_off = __libdw_cu_ranges_base (cu);
     421                 :            : 
     422                 :            :       /* The section should at least contain room for one offset.  */
     423                 :         40 :       size_t sec_size = cu->dbg->sectiondata[secidx]->d_size;
     424                 :         40 :       size_t offset_size = cu->offset_size;
     425         [ -  + ]:         40 :       if (offset_size > sec_size)
     426                 :            :         {
     427                 :          0 :         invalid_offset:
     428                 :          0 :           __libdw_seterrno (DWARF_E_INVALID_OFFSET);
     429                 :          0 :           return -1;
     430                 :            :         }
     431                 :            : 
     432                 :            :       /* And the base offset should be at least inside the section.  */
     433         [ -  + ]:         40 :       if (range_base_off > (sec_size - offset_size))
     434                 :          0 :         goto invalid_offset;
     435                 :            : 
     436                 :         40 :       size_t max_idx = (sec_size - offset_size - range_base_off) / offset_size;
     437         [ -  + ]:         40 :       if (idx > max_idx)
     438                 :          0 :         goto invalid_offset;
     439                 :            : 
     440                 :         40 :       datap = (cu->dbg->sectiondata[secidx]->d_buf
     441                 :         40 :                + range_base_off + (idx * offset_size));
     442         [ +  - ]:         40 :       if (offset_size == 4)
     443         [ -  + ]:         40 :         start_offset = read_4ubyte_unaligned (cu->dbg, datap);
     444                 :            :       else
     445         [ #  # ]:          0 :         start_offset = read_8ubyte_unaligned (cu->dbg, datap);
     446                 :            : 
     447                 :         40 :       start_offset += range_base_off;
     448                 :            :     }
     449                 :            :   else
     450                 :            :     {
     451   [ +  +  -  + ]:      27632 :       if (__libdw_formptr (attr, secidx,
     452                 :            :                            (secidx == IDX_debug_ranges
     453                 :            :                             ? DWARF_E_NO_DEBUG_RANGES
     454                 :            :                             : DWARF_E_NO_DEBUG_RNGLISTS),
     455                 :            :                            NULL, &start_offset) == NULL)
     456                 :            :         return -1;
     457                 :            :     }
     458                 :            : 
     459                 :      13898 :   *offset = start_offset;
     460                 :      13898 :   return 0;
     461                 :            : }
     462                 :            : 
     463                 :            : ptrdiff_t
     464                 :    1352856 : dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
     465                 :            :               Dwarf_Addr *startp, Dwarf_Addr *endp)
     466                 :            : {
     467         [ -  + ]:    1352856 :   if (die == NULL)
     468                 :            :     return -1;
     469                 :            : 
     470         [ +  + ]:    1352856 :   if (offset == 0
     471                 :            :       /* Usually there is a single contiguous range.  */
     472         [ +  + ]:    1344132 :       && INTUSE(dwarf_highpc) (die, endp) == 0
     473         [ -  + ]:       9536 :       && INTUSE(dwarf_lowpc) (die, startp) == 0)
     474                 :            :     /* A offset into .debug_ranges will never be 1, it must be at least a
     475                 :            :        multiple of 4.  So we can return 1 as a special case value to mark
     476                 :            :        there are no ranges to look for on the next call.  */
     477                 :            :     return 1;
     478                 :            : 
     479         [ +  + ]:    1343320 :   if (offset == 1)
     480                 :            :     return 0;
     481                 :            : 
     482                 :            :   /* We have to look for a noncontiguous range.  */
     483                 :    1334800 :   Dwarf_CU *cu = die->cu;
     484         [ +  + ]:    1334800 :   if (cu == NULL)
     485                 :            :     {
     486                 :       2370 :       __libdw_seterrno (DWARF_E_INVALID_DWARF);
     487                 :       2370 :       return -1;
     488                 :            :     }
     489                 :            : 
     490         [ +  + ]:    1332430 :   size_t secidx = (cu->version < 5 ? IDX_debug_ranges : IDX_debug_rnglists);
     491                 :    1332430 :   const Elf_Data *d = cu->dbg->sectiondata[secidx];
     492   [ +  +  +  +  :    1332430 :   if (cu->unit_type == DW_UT_split_compile && (d == NULL || is_cudie (die)))
                   +  + ]
     493                 :            :     {
     494                 :        488 :       Dwarf_CU *skel = __libdw_find_split_unit (cu);
     495   [ -  +  -  + ]:        488 :       if (skel != NULL && skel->dbg->sectiondata[secidx] != NULL)
     496                 :            :         {
     497                 :    1332430 :           cu = skel;
     498                 :    1332430 :           d = cu->dbg->sectiondata[secidx];
     499                 :            :         }
     500                 :            :     }
     501                 :            : 
     502                 :    1332430 :   const unsigned char *readp;
     503                 :    1332430 :   const unsigned char *readendp;
     504         [ +  + ]:    1332430 :   if (offset == 0)
     505                 :            :     {
     506                 :    1332226 :       Dwarf_Attribute attr_mem;
     507                 :    1332226 :       Dwarf_Attribute *attr = INTUSE(dwarf_attr) (die, DW_AT_ranges,
     508                 :            :                                                   &attr_mem);
     509                 :            :       /* Note that above we use dwarf_attr, not dwarf_attr_integrate.
     510                 :            :          The only case where the ranges can come from another DIE
     511                 :            :          attribute are the split CU case. In that case we also have a
     512                 :            :          different CU to check against. But that is already set up
     513                 :            :          above using __libdw_find_split_unit.  */
     514         [ +  + ]:    1332226 :       if (attr == NULL
     515         [ +  + ]:    1318348 :           && is_cudie (die)
     516         [ +  + ]:         36 :           && die->cu->unit_type == DW_UT_split_compile)
     517                 :         20 :         attr = INTUSE(dwarf_attr_integrate) (die, DW_AT_ranges, &attr_mem);
     518         [ +  + ]:    1318348 :       if (attr == NULL)
     519                 :            :         /* No PC attributes in this DIE at all, so an empty range list.  */
     520                 :    1318328 :         return 0;
     521                 :            : 
     522                 :      13898 :       *basep = __libdw_cu_base_address (attr->cu);
     523         [ +  - ]:      13898 :       if (*basep == (Dwarf_Addr) -1)
     524                 :            :         return -1;
     525                 :            : 
     526         [ +  - ]:      13898 :       if (initial_offset (attr, &offset) != 0)
     527                 :            :         return -1;
     528                 :            :     }
     529                 :            :   else
     530                 :            :     {
     531         [ -  + ]:        204 :       if (__libdw_offset_in_section (cu->dbg,
     532                 :            :                                      secidx, offset, 1))
     533                 :            :         return -1;
     534                 :            :     }
     535                 :            : 
     536                 :      14102 :   readp = d->d_buf + offset;
     537                 :      14102 :   readendp = d->d_buf + d->d_size;
     538                 :            : 
     539                 :      16826 :   Dwarf_Addr begin;
     540                 :      16826 :   Dwarf_Addr end;
     541                 :            : 
     542                 :      16826 :  next:
     543   [ -  +  +  + ]:      16826 :   switch (__libdw_read_begin_end_pair_inc (cu, secidx,
     544                 :            :                                            &readp, readendp,
     545                 :      16826 :                                            cu->address_size,
     546                 :            :                                            &begin, &end, basep))
     547                 :            :     {
     548                 :            :     case 0:
     549                 :      14016 :       break;
     550                 :       2724 :     case 1:
     551                 :       2724 :       goto next;
     552                 :            :     case 2:
     553                 :            :       return 0;
     554                 :            :     default:
     555                 :            :       return -1;
     556                 :            :     }
     557                 :            : 
     558                 :      14016 :   *startp = begin;
     559                 :      14016 :   *endp = end;
     560                 :      14016 :   return readp - (unsigned char *) d->d_buf;
     561                 :            : }
     562                 :            : INTDEF (dwarf_ranges)

Generated by: LCOV version 1.16