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

             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                 :     3583446 : __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                 :     3583446 :   Dwarf *dbg = cu->dbg;
      52         [ +  + ]:     3583446 :   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         [ +  + ]:     3582822 :   else if (sec_index == IDX_debug_ranges || sec_index == IDX_debug_loc)
     116                 :             :     {
     117                 :         996 :       Dwarf_Addr escape = (width == 8 ? (Elf64_Addr) -1
     118         [ -  + ]:         498 :                            : (Elf64_Addr) (Elf32_Addr) -1);
     119                 :         498 :       Dwarf_Addr begin;
     120                 :         498 :       Dwarf_Addr end;
     121                 :             : 
     122                 :         498 :       const unsigned char *addr = *addrp;
     123         [ -  + ]:         498 :       if (addrend - addr < width * 2)
     124                 :             :         {
     125                 :           0 :         invalid:
     126                 :           0 :           __libdw_seterrno (DWARF_E_INVALID_DWARF);
     127                 :           0 :           return -1;
     128                 :             :         }
     129                 :             : 
     130   [ -  +  -  +  :         498 :       bool begin_relocated = READ_AND_RELOCATE (__libdw_relocate_address,
             -  -  -  + ]
     131                 :             :                                                 begin);
     132   [ -  +  -  +  :         498 :       bool end_relocated = READ_AND_RELOCATE (__libdw_relocate_address,
             -  -  -  + ]
     133                 :             :                                               end);
     134                 :         498 :       *addrp = addr;
     135                 :             : 
     136                 :             :       /* Unrelocated escape for begin means base address selection.  */
     137         [ +  + ]:         498 :       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   [ +  +  +  + ]:         496 :       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                 :         428 :       *beginp = begin + *basep;
     153                 :         428 :       *endp = end + *basep;
     154                 :             : 
     155                 :         428 :       return 0;
     156                 :             :     }
     157         [ +  + ]:     3582324 :   else if (sec_index == IDX_debug_rnglists)
     158                 :             :     {
     159                 :       23072 :       const unsigned char *addr = *addrp;
     160         [ -  + ]:       23072 :       if (addrend - addr < 1)
     161                 :           0 :         goto invalid;
     162                 :             : 
     163                 :       23072 :       const char code = *addr++;
     164                 :       23072 :       uint64_t begin = 0, end = 0, base = *basep, addr_idx;
     165   [ +  +  -  +  :       23072 :       switch (code)
             +  +  -  +  
                      - ]
     166                 :             :         {
     167                 :          34 :         case DW_RLE_end_of_list:
     168                 :          34 :           *addrp = addr;
     169                 :       23072 :           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                 :       13732 :         case DW_RLE_offset_pair:
     215         [ -  + ]:       13732 :           if (addrend - addr < 1)
     216                 :           0 :             goto invalid;
     217                 :       13732 :           get_uleb128 (begin, addr, addrend);
     218         [ -  + ]:       13732 :           if (addrend - addr < 1)
     219                 :           0 :             goto invalid;
     220                 :       13732 :           get_uleb128 (end, addr, addrend);
     221                 :             : 
     222                 :       13732 :           *beginp = begin + base;
     223                 :       13732 :           *endp = end + base;
     224                 :       13732 :           *addrp = addr;
     225                 :       13732 :           return 0;
     226                 :             : 
     227                 :        7650 :         case DW_RLE_base_address:
     228         [ -  + ]:        7650 :           if (addrend - addr < width)
     229                 :           0 :             goto invalid;
     230                 :        7650 :           __libdw_read_address_inc (dbg, sec_index, &addr, width, &base);
     231                 :             : 
     232                 :        7650 :           *basep = base;
     233                 :        7650 :           *addrp = addr;
     234                 :        7650 :           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                 :        1632 :         case DW_RLE_start_length:
     248         [ -  + ]:        1632 :           if (addrend - addr < width)
     249                 :           0 :             goto invalid;
     250                 :        1632 :           __libdw_read_address_inc (dbg, sec_index, &addr, width, &begin);
     251         [ -  + ]:        1632 :           if (addrend - addr < 1)
     252                 :           0 :             goto invalid;
     253                 :        1632 :           get_uleb128 (end, addr, addrend);
     254                 :             : 
     255                 :        1632 :           *beginp = begin;
     256                 :        1632 :           *endp = begin + end;
     257                 :        1632 :           *addrp = addr;
     258                 :        1632 :           return 0;
     259                 :             : 
     260                 :           0 :         default:
     261                 :           0 :           goto invalid;
     262                 :             :         }
     263                 :             :     }
     264         [ +  - ]:     3559252 :   else if (sec_index == IDX_debug_loclists)
     265                 :             :     {
     266                 :     3559252 :       const unsigned char *addr = *addrp;
     267         [ -  + ]:     3559252 :       if (addrend - addr < 1)
     268                 :           0 :         goto invalid;
     269                 :             : 
     270                 :     3559252 :       const char code = *addr++;
     271                 :     3559252 :       uint64_t begin = 0, end = 0, base = *basep, addr_idx;
     272   [ +  -  -  +  :     3559252 :       switch (code)
          +  -  +  -  +  
                      - ]
     273                 :             :         {
     274                 :      129732 :         case DW_LLE_end_of_list:
     275                 :      129732 :           *addrp = addr;
     276                 :     3559252 :           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                 :     3220332 :         case DW_LLE_offset_pair:
     322         [ -  + ]:     3220332 :           if (addrend - addr < 1)
     323                 :           0 :             goto invalid;
     324                 :     3220332 :           get_uleb128 (begin, addr, addrend);
     325         [ -  + ]:     3220332 :           if (addrend - addr < 1)
     326                 :           0 :             goto invalid;
     327                 :     3220332 :           get_uleb128 (end, addr, addrend);
     328                 :             : 
     329                 :     3220332 :           *beginp = begin + base;
     330                 :     3220332 :           *endp = end + base;
     331                 :     3220332 :           *addrp = addr;
     332                 :     3220332 :           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                 :      175518 :         case DW_LLE_base_address:
     341         [ -  + ]:      175518 :           if (addrend - addr < width)
     342                 :           0 :             goto invalid;
     343                 :      175518 :           __libdw_read_address_inc (dbg, sec_index, &addr, width, &base);
     344                 :             : 
     345                 :      175518 :           *basep = base;
     346                 :      175518 :           *addrp = addr;
     347                 :      175518 :           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                 :       33216 :         case DW_LLE_start_length:
     361         [ -  + ]:       33216 :           if (addrend - addr < width)
     362                 :           0 :             goto invalid;
     363                 :       33216 :           __libdw_read_address_inc (dbg, sec_index, &addr, width, &begin);
     364         [ -  + ]:       33216 :           if (addrend - addr < 1)
     365                 :           0 :             goto invalid;
     366                 :       33216 :           get_uleb128 (end, addr, addrend);
     367                 :             : 
     368                 :       33216 :           *beginp = begin;
     369                 :       33216 :           *endp = begin + end;
     370                 :       33216 :           *addrp = addr;
     371                 :       33216 :           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                 :       15398 : initial_offset (Dwarf_Attribute *attr, ptrdiff_t *offset)
     386                 :             : {
     387                 :       30796 :   size_t secidx = (attr->cu->version < 5
     388         [ +  + ]:       15398 :                    ? IDX_debug_ranges : IDX_debug_rnglists);
     389                 :             : 
     390                 :       15398 :   Dwarf_Word start_offset;
     391         [ +  + ]:       15398 :   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   [ +  +  -  + ]:       30628 :       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                 :       15398 :   *offset = start_offset;
     460                 :       15398 :   return 0;
     461                 :             : }
     462                 :             : 
     463                 :             : ptrdiff_t
     464                 :     1394060 : dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
     465                 :             :               Dwarf_Addr *startp, Dwarf_Addr *endp)
     466                 :             : {
     467         [ -  + ]:     1394060 :   if (die == NULL)
     468                 :             :     return -1;
     469                 :             : 
     470         [ +  + ]:     1394060 :   if (offset == 0
     471                 :             :       /* Usually there is a single contiguous range.  */
     472         [ +  + ]:     1386644 :       && INTUSE(dwarf_highpc) (die, endp) == 0
     473         [ -  + ]:        8242 :       && 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         [ +  + ]:     1385818 :   if (offset == 1)
     480                 :             :     return 0;
     481                 :             : 
     482                 :             :   /* We have to look for a noncontiguous range.  */
     483                 :     1378606 :   Dwarf_CU *cu = die->cu;
     484         [ +  + ]:     1378606 :   if (cu == NULL)
     485                 :             :     {
     486                 :        2422 :       __libdw_seterrno (DWARF_E_INVALID_DWARF);
     487                 :        2422 :       return -1;
     488                 :             :     }
     489                 :             : 
     490         [ +  + ]:     1376184 :   size_t secidx = (cu->version < 5 ? IDX_debug_ranges : IDX_debug_rnglists);
     491                 :     1376184 :   const Elf_Data *d = cu->dbg->sectiondata[secidx];
     492   [ +  +  +  +  :     1376184 :   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                 :     1376184 :           cu = skel;
     498                 :     1376184 :           d = cu->dbg->sectiondata[secidx];
     499                 :             :         }
     500                 :             :     }
     501                 :             : 
     502                 :     1376184 :   const unsigned char *readp;
     503                 :     1376184 :   const unsigned char *readendp;
     504         [ +  + ]:     1376184 :   if (offset == 0)
     505                 :             :     {
     506                 :     1375980 :       Dwarf_Attribute attr_mem;
     507                 :     1375980 :       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         [ +  + ]:     1375980 :       if (attr == NULL
     515         [ +  + ]:     1360602 :           && 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         [ +  + ]:     1360602 :       if (attr == NULL)
     519                 :             :         /* No PC attributes in this DIE at all, so an empty range list.  */
     520                 :     1360582 :         return 0;
     521                 :             : 
     522                 :       15398 :       *basep = __libdw_cu_base_address (attr->cu);
     523         [ +  - ]:       15398 :       if (*basep == (Dwarf_Addr) -1)
     524                 :             :         return -1;
     525                 :             : 
     526         [ +  - ]:       15398 :       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                 :       15602 :   readp = d->d_buf + offset;
     537                 :       15602 :   readendp = d->d_buf + d->d_size;
     538                 :             : 
     539                 :       23274 :   Dwarf_Addr begin;
     540                 :       23274 :   Dwarf_Addr end;
     541                 :             : 
     542                 :       23274 :  next:
     543   [ -  +  +  + ]:       23274 :   switch (__libdw_read_begin_end_pair_inc (cu, secidx,
     544                 :             :                                            &readp, readendp,
     545                 :       23274 :                                            cu->address_size,
     546                 :             :                                            &begin, &end, basep))
     547                 :             :     {
     548                 :             :     case 0:
     549                 :       15518 :       break;
     550                 :        7672 :     case 1:
     551                 :        7672 :       goto next;
     552                 :             :     case 2:
     553                 :             :       return 0;
     554                 :             :     default:
     555                 :             :       return -1;
     556                 :             :     }
     557                 :             : 
     558                 :       15518 :   *startp = begin;
     559                 :       15518 :   *endp = end;
     560                 :       15518 :   return readp - (unsigned char *) d->d_buf;
     561                 :             : }
     562                 :             : INTDEF (dwarf_ranges)
        

Generated by: LCOV version 2.0-1