LCOV - code coverage report
Current view: top level - libdw - dwarf_getlocation.c (source / functions) Hit Total Coverage
Test: elfutils-0.191 Lines: 324 435 74.5 %
Date: 2024-09-20 16:41:50 Functions: 13 13 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 185 316 58.5 %

           Branch data     Line data    Source code
       1                 :            : /* Return location expression list.
       2                 :            :    Copyright (C) 2000-2010, 2013-2015, 2017, 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 <dwarf.h>
      34                 :            : #include <stdlib.h>
      35                 :            : #include <assert.h>
      36                 :            : 
      37                 :            : #include <libdwP.h>
      38                 :            : #include "eu-search.h"
      39                 :            : 
      40                 :            : 
      41                 :            : static bool
      42                 :   11217026 : attr_ok (Dwarf_Attribute *attr)
      43                 :            : {
      44         [ -  + ]:   11217026 :   if (attr == NULL)
      45                 :            :     return false;
      46                 :            : 
      47                 :            :   /* If it is an exprloc, it is obviously OK.  */
      48         [ +  + ]:   11217026 :   if (dwarf_whatform (attr) == DW_FORM_exprloc)
      49                 :            :     return true;
      50                 :            : 
      51         [ +  - ]:   10963682 :   if (attr->cu->version >= 4)
      52                 :            :     {
      53                 :            :       /* Must be an exprloc (or constant), just not any block form.  */
      54         [ -  + ]:   10963682 :       switch (dwarf_whatform (attr))
      55                 :            :         {
      56                 :          0 :         case DW_FORM_block:
      57                 :            :         case DW_FORM_block1:
      58                 :            :         case DW_FORM_block2:
      59                 :            :         case DW_FORM_block4:
      60                 :          0 :           __libdw_seterrno (DWARF_E_NO_LOC_VALUE);
      61                 :          0 :           return false;
      62                 :            :         default:
      63                 :            :           break;
      64                 :            :         }
      65                 :            :     }
      66                 :            : 
      67                 :            :   /* Otherwise must be one of the attributes listed below.  Older
      68                 :            :      DWARF versions might have encoded the exprloc as block, and we
      69                 :            :      cannot easily distinguish attributes in the loclist class because
      70                 :            :      the same forms are used for different classes.  */
      71         [ +  + ]:   10963682 :   switch (attr->code)
      72                 :            :     {
      73                 :            :     case DW_AT_location:
      74                 :            :     case DW_AT_byte_size:
      75                 :            :     case DW_AT_bit_offset:
      76                 :            :     case DW_AT_bit_size:
      77                 :            :     case DW_AT_lower_bound:
      78                 :            :     case DW_AT_bit_stride:
      79                 :            :     case DW_AT_upper_bound:
      80                 :            :     case DW_AT_count:
      81                 :            :     case DW_AT_allocated:
      82                 :            :     case DW_AT_associated:
      83                 :            :     case DW_AT_data_location:
      84                 :            :     case DW_AT_byte_stride:
      85                 :            :     case DW_AT_rank:
      86                 :            :     case DW_AT_call_value:
      87                 :            :     case DW_AT_call_target:
      88                 :            :     case DW_AT_call_target_clobbered:
      89                 :            :     case DW_AT_call_data_location:
      90                 :            :     case DW_AT_call_data_value:
      91                 :            :     case DW_AT_data_member_location:
      92                 :            :     case DW_AT_vtable_elem_location:
      93                 :            :     case DW_AT_string_length:
      94                 :            :     case DW_AT_use_location:
      95                 :            :     case DW_AT_frame_base:
      96                 :            :     case DW_AT_return_addr:
      97                 :            :     case DW_AT_static_link:
      98                 :            :     case DW_AT_segment:
      99                 :            :     case DW_AT_GNU_call_site_value:
     100                 :            :     case DW_AT_GNU_call_site_data_value:
     101                 :            :     case DW_AT_GNU_call_site_target:
     102                 :            :     case DW_AT_GNU_call_site_target_clobbered:
     103                 :            :       break;
     104                 :            : 
     105                 :    8924828 :     default:
     106                 :    8924828 :       __libdw_seterrno (DWARF_E_NO_LOC_VALUE);
     107                 :    8924828 :       return false;
     108                 :            :     }
     109                 :            : 
     110                 :            :   return true;
     111                 :            : }
     112                 :            : 
     113                 :            : 
     114                 :            : struct loclist
     115                 :            : {
     116                 :            :   uint8_t atom;
     117                 :            :   Dwarf_Word number;
     118                 :            :   Dwarf_Word number2;
     119                 :            :   Dwarf_Word offset;
     120                 :            :   struct loclist *next;
     121                 :            : };
     122                 :            : 
     123                 :            : 
     124                 :            : static int
     125                 :   32047610 : loc_compare (const void *p1, const void *p2)
     126                 :            : {
     127                 :   32047610 :   const struct loc_s *l1 = (const struct loc_s *) p1;
     128                 :   32047610 :   const struct loc_s *l2 = (const struct loc_s *) p2;
     129                 :            : 
     130         [ +  + ]:   32047610 :   if ((uintptr_t) l1->addr < (uintptr_t) l2->addr)
     131                 :            :     return -1;
     132         [ +  + ]:   29999476 :   if ((uintptr_t) l1->addr > (uintptr_t) l2->addr)
     133                 :   29533854 :     return 1;
     134                 :            : 
     135                 :            :   return 0;
     136                 :            : }
     137                 :            : 
     138                 :            : /* For each DW_OP_implicit_value, we store a special entry in the cache.
     139                 :            :    This points us directly to the block data for later fetching.
     140                 :            :    Returns zero on success, -1 on bad DWARF or 1 if eu_tsearch failed.  */
     141                 :            : static int
     142                 :        606 : store_implicit_value (Dwarf *dbg, search_tree *cache, Dwarf_Op *op)
     143                 :            : {
     144         [ -  + ]:        606 :   if (dbg == NULL)
     145                 :            :     return -1;
     146         [ +  + ]:        606 :   struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s,
     147                 :            :                                            sizeof (struct loc_block_s), 1);
     148                 :        606 :   const unsigned char *data = (const unsigned char *) (uintptr_t) op->number2;
     149                 :            :   /* Skip the block length.  */
     150                 :        606 :   Dwarf_Word length;
     151                 :        606 :   get_uleb128_unchecked (length, data);
     152         [ -  + ]:        606 :   if (length != op->number)
     153                 :            :     return -1;
     154                 :        606 :   block->addr = op;
     155                 :        606 :   block->data = (unsigned char *) data;
     156                 :        606 :   block->length = op->number;
     157         [ -  + ]:        606 :   if (unlikely (eu_tsearch (block, cache, loc_compare) == NULL))
     158                 :          0 :     return 1;
     159                 :            :   return 0;
     160                 :            : }
     161                 :            : 
     162                 :            : int
     163                 :       1498 : dwarf_getlocation_implicit_value (Dwarf_Attribute *attr, const Dwarf_Op *op,
     164                 :            :                                   Dwarf_Block *return_block)
     165                 :            : {
     166         [ -  + ]:       1498 :   if (attr == NULL)
     167                 :            :     return -1;
     168                 :            : 
     169                 :       1498 :   struct loc_block_s fake = { .addr = (void *) op };
     170                 :       1498 :   struct loc_block_s **found = eu_tfind (&fake, &attr->cu->locs_tree,
     171                 :            :                                          loc_compare);
     172         [ -  + ]:       1498 :   if (unlikely (found == NULL))
     173                 :            :     {
     174                 :          0 :       __libdw_seterrno (DWARF_E_NO_BLOCK);
     175                 :          0 :       return -1;
     176                 :            :     }
     177                 :            : 
     178                 :       1498 :   return_block->length = (*found)->length;
     179                 :       1498 :   return_block->data = (*found)->data;
     180                 :       1498 :   return 0;
     181                 :            : }
     182                 :            : 
     183                 :            : /* If the given attribute is DW_AT_data_member_location and it has constant
     184                 :            :    form then create a fake location using DW_OP_plus_uconst and the offset
     185                 :            :    value.  On success returns zero and fills in llbuf (when not NULL) and
     186                 :            :    sets listlen to 1.  Returns 1 when this isn't a DW_AT_data_member_location
     187                 :            :    offset.  Returns -1 and sets dwarf_errno on failure (bad DWARF data).  */
     188                 :            : static int
     189                 :    1708128 : is_constant_offset (Dwarf_Attribute *attr,
     190                 :            :                     Dwarf_Op **llbuf, size_t *listlen)
     191                 :            : {
     192         [ +  + ]:    1708128 :   if (attr->code != DW_AT_data_member_location)
     193                 :            :     return 1;
     194                 :            : 
     195         [ +  - ]:     353184 :   switch (attr->form)
     196                 :            :     {
     197                 :            :       /* Punt for any non-constant form.  */
     198                 :            :     default:
     199                 :            :       return 1;
     200                 :            : 
     201                 :            :       /* Note, we don't regard DW_FORM_data16 as a constant form,
     202                 :            :          even though technically it is according to the standard.  */
     203                 :            :     case DW_FORM_data1:
     204                 :            :     case DW_FORM_data2:
     205                 :            :     case DW_FORM_data4:
     206                 :            :     case DW_FORM_data8:
     207                 :            :     case DW_FORM_sdata:
     208                 :            :     case DW_FORM_udata:
     209                 :            :     case DW_FORM_implicit_const:
     210                 :     353184 :       break;
     211                 :            :     }
     212                 :            : 
     213                 :            :   /* Check whether we already cached this location.  */
     214                 :     353184 :   struct loc_s fake = { .addr = attr->valp };
     215                 :     353184 :   struct loc_s **found = eu_tfind (&fake, &attr->cu->locs_tree, loc_compare);
     216                 :            : 
     217         [ +  + ]:     353184 :   if (found == NULL)
     218                 :            :     {
     219                 :     353176 :       Dwarf_Word offset;
     220         [ -  + ]:     353176 :       if (INTUSE(dwarf_formudata) (attr, &offset) != 0)
     221                 :          0 :         return -1;
     222                 :            : 
     223         [ +  + ]:     353176 :       Dwarf_Op *result = libdw_alloc (attr->cu->dbg,
     224                 :            :                                       Dwarf_Op, sizeof (Dwarf_Op), 1);
     225                 :            : 
     226                 :     353176 :       result->atom = DW_OP_plus_uconst;
     227                 :     353176 :       result->number = offset;
     228                 :     353176 :       result->number2 = 0;
     229                 :     353176 :       result->offset = 0;
     230                 :            : 
     231                 :            :       /* Insert a record in the search tree so we can find it again later.  */
     232         [ +  + ]:     353176 :       struct loc_s *newp = libdw_alloc (attr->cu->dbg,
     233                 :            :                                         struct loc_s, sizeof (struct loc_s),
     234                 :            :                                         1);
     235                 :     353176 :       newp->addr = attr->valp;
     236                 :     353176 :       newp->loc = result;
     237                 :     353176 :       newp->nloc = 1;
     238                 :            : 
     239                 :     353176 :       found = eu_tsearch (newp, &attr->cu->locs_tree, loc_compare);
     240                 :            :     }
     241                 :            : 
     242         [ -  + ]:     353184 :   assert ((*found)->nloc == 1);
     243                 :            : 
     244         [ +  - ]:     353184 :   if (llbuf != NULL)
     245                 :            :     {
     246                 :     353184 :       *llbuf = (*found)->loc;
     247                 :     353184 :       *listlen = 1;
     248                 :            :     }
     249                 :            : 
     250                 :            :   return 0;
     251                 :            : }
     252                 :            : 
     253                 :            : int
     254                 :            : internal_function
     255                 :    1298674 : __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
     256                 :            :                            unsigned int address_size, unsigned int ref_size,
     257                 :            :                            search_tree *cache, const Dwarf_Block *block,
     258                 :            :                            bool cfap, bool valuep,
     259                 :            :                            Dwarf_Op **llbuf, size_t *listlen, int sec_index)
     260                 :            : {
     261                 :            :   /* Empty location expressions don't have any ops to intern.  */
     262         [ -  + ]:    1298674 :   if (block->length == 0)
     263                 :            :     {
     264                 :          0 :       *listlen = 0;
     265                 :          0 :       return 0;
     266                 :            :     }
     267                 :            : 
     268                 :            :   /* Check whether we already looked at this list.  */
     269                 :    1298674 :   struct loc_s fake = { .addr = block->data };
     270                 :    1298674 :   struct loc_s **found = eu_tfind (&fake, cache, loc_compare);
     271         [ +  + ]:    1298674 :   if (found != NULL)
     272                 :            :     {
     273                 :            :       /* We already saw it.  */
     274                 :     464116 :       *llbuf = (*found)->loc;
     275                 :     464116 :       *listlen = (*found)->nloc;
     276                 :            : 
     277         [ +  - ]:     464116 :       if (valuep)
     278                 :            :         {
     279         [ #  # ]:          0 :           assert (*listlen > 1);
     280         [ #  # ]:          0 :           assert ((*llbuf)[*listlen - 1].atom == DW_OP_stack_value);
     281                 :            :         }
     282                 :            : 
     283                 :            :       return 0;
     284                 :            :     }
     285                 :            : 
     286                 :     834558 :   const unsigned char *data = block->data;
     287                 :     834558 :   const unsigned char *const end_data = data + block->length;
     288                 :            : 
     289                 :     834558 :   const struct { bool other_byte_order; } bo = { other_byte_order };
     290                 :            : 
     291                 :     834558 :   struct loclist *loclist = NULL;
     292                 :     834558 :   unsigned int n = 0;
     293                 :            : 
     294                 :            :   /* Stack allocate at most this many locs.  */
     295                 :            : #define MAX_STACK_LOCS 256
     296                 :     834558 :   struct loclist stack_locs[MAX_STACK_LOCS];
     297                 :            : #define NEW_LOC() ({ struct loclist *ll;                        \
     298                 :            :                      ll = (likely (n < MAX_STACK_LOCS)               \
     299                 :            :                            ? &stack_locs[n]                 \
     300                 :            :                            : malloc (sizeof (struct loclist))); \
     301                 :            :                      if (unlikely (ll == NULL))                 \
     302                 :            :                        goto nomem;                              \
     303                 :            :                      n++;                                       \
     304                 :            :                      ll->next = loclist;                     \
     305                 :            :                      loclist = ll;                              \
     306                 :            :                      ll; })
     307                 :            : 
     308         [ +  + ]:     834558 :   if (cfap)
     309                 :            :     {
     310                 :            :       /* Synthesize the operation to push the CFA before the expression.  */
     311                 :          2 :       struct loclist *newloc = NEW_LOC ();
     312                 :          2 :       newloc->atom = DW_OP_call_frame_cfa;
     313                 :          2 :       newloc->number = 0;
     314                 :          2 :       newloc->number2 = 0;
     315                 :          2 :       newloc->offset = -1;
     316                 :            :     }
     317                 :            : 
     318                 :            :   /* Decode the opcodes.  It is possible in some situations to have a
     319                 :            :      block of size zero.  */
     320         [ +  + ]:    2064038 :   while (data < end_data)
     321                 :            :     {
     322                 :    1229480 :       struct loclist *newloc;
     323   [ +  +  -  + ]:    1229480 :       newloc = NEW_LOC ();
     324                 :    1229480 :       newloc->number = 0;
     325                 :    1229480 :       newloc->number2 = 0;
     326                 :    1229480 :       newloc->offset = data - block->data;
     327                 :            : 
     328   [ +  +  +  +  :    1229480 :       switch ((newloc->atom = *data++))
          +  +  +  +  +  
          -  +  +  -  -  
          +  +  +  +  -  
                      + ]
     329                 :            :         {
     330                 :      26160 :         case DW_OP_addr:
     331                 :            :           /* Address, depends on address size of CU.  */
     332         [ -  + ]:      26160 :           if (dbg == NULL)
     333                 :            :             {
     334                 :            :               // XXX relocation?
     335         [ #  # ]:          0 :               if (address_size == 4)
     336                 :            :                 {
     337         [ #  # ]:          0 :                   if (unlikely (data + 4 > end_data))
     338                 :          0 :                     goto invalid;
     339                 :            :                   else
     340         [ #  # ]:          0 :                     newloc->number = read_4ubyte_unaligned_inc (&bo, data);
     341                 :            :                 }
     342                 :            :               else
     343                 :            :                 {
     344         [ #  # ]:          0 :                   if (unlikely (data + 8 > end_data))
     345                 :          0 :                     goto invalid;
     346                 :            :                   else
     347         [ #  # ]:          0 :                     newloc->number = read_8ubyte_unaligned_inc (&bo, data);
     348                 :            :                 }
     349                 :            :             }
     350         [ -  + ]:      26160 :           else if (__libdw_read_address_inc (dbg, sec_index, &data,
     351                 :      26160 :                                              address_size, &newloc->number))
     352                 :          0 :             goto invalid;
     353                 :            :           break;
     354                 :            : 
     355                 :          2 :         case DW_OP_call_ref:
     356                 :            :         case DW_OP_GNU_variable_value:
     357                 :            :           /* DW_FORM_ref_addr, depends on offset size of CU.  */
     358   [ +  -  -  + ]:          4 :           if (dbg == NULL || __libdw_read_offset_inc (dbg, sec_index, &data,
     359                 :            :                                                       ref_size,
     360                 :          2 :                                                       &newloc->number,
     361                 :            :                                                       IDX_debug_info, 0))
     362                 :          0 :             goto invalid;
     363                 :            :           break;
     364                 :            : 
     365                 :            :         case DW_OP_deref:
     366                 :            :         case DW_OP_dup:
     367                 :            :         case DW_OP_drop:
     368                 :            :         case DW_OP_over:
     369                 :            :         case DW_OP_swap:
     370                 :            :         case DW_OP_rot:
     371                 :            :         case DW_OP_xderef:
     372                 :            :         case DW_OP_abs:
     373                 :            :         case DW_OP_and:
     374                 :            :         case DW_OP_div:
     375                 :            :         case DW_OP_minus:
     376                 :            :         case DW_OP_mod:
     377                 :            :         case DW_OP_mul:
     378                 :            :         case DW_OP_neg:
     379                 :            :         case DW_OP_not:
     380                 :            :         case DW_OP_or:
     381                 :            :         case DW_OP_plus:
     382                 :            :         case DW_OP_shl:
     383                 :            :         case DW_OP_shr:
     384                 :            :         case DW_OP_shra:
     385                 :            :         case DW_OP_xor:
     386                 :            :         case DW_OP_eq:
     387                 :            :         case DW_OP_ge:
     388                 :            :         case DW_OP_gt:
     389                 :            :         case DW_OP_le:
     390                 :            :         case DW_OP_lt:
     391                 :            :         case DW_OP_ne:
     392                 :            :         case DW_OP_lit0 ... DW_OP_lit31:
     393                 :            :         case DW_OP_reg0 ... DW_OP_reg31:
     394                 :            :         case DW_OP_nop:
     395                 :            :         case DW_OP_push_object_address:
     396                 :            :         case DW_OP_call_frame_cfa:
     397                 :            :         case DW_OP_form_tls_address:
     398                 :            :         case DW_OP_GNU_push_tls_address:
     399                 :            :         case DW_OP_stack_value:
     400                 :            :         case DW_OP_GNU_uninit:
     401                 :            :           /* No operand.  */
     402                 :            :           break;
     403                 :            : 
     404                 :      24050 :         case DW_OP_const1u:
     405                 :            :         case DW_OP_pick:
     406                 :            :         case DW_OP_deref_size:
     407                 :            :         case DW_OP_xderef_size:
     408         [ -  + ]:      24050 :           if (unlikely (data >= end_data))
     409                 :            :             {
     410                 :          0 :             invalid:
     411                 :          0 :               __libdw_seterrno (DWARF_E_INVALID_DWARF);
     412                 :            :             returnmem:
     413                 :            :               /* Free any dynamically allocated loclists, if any.  */
     414         [ #  # ]:          0 :               while (n > MAX_STACK_LOCS)
     415                 :            :                 {
     416                 :          0 :                   struct loclist *loc = loclist;
     417                 :          0 :                   loclist = loc->next;
     418                 :          0 :                   free (loc);
     419                 :          0 :                   n--;
     420                 :            :                 }
     421                 :            :               return -1;
     422                 :            :             }
     423                 :            : 
     424                 :      24050 :           newloc->number = *data++;
     425                 :      24050 :           break;
     426                 :            : 
     427                 :       3582 :         case DW_OP_const1s:
     428         [ -  + ]:       3582 :           if (unlikely (data >= end_data))
     429                 :          0 :             goto invalid;
     430                 :            : 
     431                 :       3582 :           newloc->number = *((int8_t *) data);
     432                 :       3582 :           ++data;
     433                 :       3582 :           break;
     434                 :            : 
     435                 :       2532 :         case DW_OP_const2u:
     436         [ -  + ]:       2532 :           if (unlikely (data + 2 > end_data))
     437                 :          0 :             goto invalid;
     438                 :            : 
     439         [ -  + ]:       2532 :           newloc->number = read_2ubyte_unaligned_inc (&bo, data);
     440                 :       2532 :           break;
     441                 :            : 
     442                 :       1178 :         case DW_OP_const2s:
     443                 :            :         case DW_OP_skip:
     444                 :            :         case DW_OP_bra:
     445                 :            :         case DW_OP_call2:
     446         [ -  + ]:       1178 :           if (unlikely (data + 2 > end_data))
     447                 :          0 :             goto invalid;
     448                 :            : 
     449         [ -  + ]:       1178 :           newloc->number = read_2sbyte_unaligned_inc (&bo, data);
     450                 :       1178 :           break;
     451                 :            : 
     452                 :       2042 :         case DW_OP_const4u:
     453         [ -  + ]:       2042 :           if (unlikely (data + 4 > end_data))
     454                 :          0 :             goto invalid;
     455                 :            : 
     456         [ -  + ]:       2042 :           newloc->number = read_4ubyte_unaligned_inc (&bo, data);
     457                 :       2042 :           break;
     458                 :            : 
     459                 :         22 :         case DW_OP_const4s:
     460                 :            :         case DW_OP_call4:
     461                 :            :         case DW_OP_GNU_parameter_ref:
     462         [ -  + ]:         22 :           if (unlikely (data + 4 > end_data))
     463                 :          0 :             goto invalid;
     464                 :            : 
     465         [ -  + ]:         22 :           newloc->number = read_4sbyte_unaligned_inc (&bo, data);
     466                 :         22 :           break;
     467                 :            : 
     468                 :        244 :         case DW_OP_const8u:
     469         [ -  + ]:        244 :           if (unlikely (data + 8 > end_data))
     470                 :          0 :             goto invalid;
     471                 :            : 
     472         [ -  + ]:        244 :           newloc->number = read_8ubyte_unaligned_inc (&bo, data);
     473                 :        244 :           break;
     474                 :            : 
     475                 :          0 :         case DW_OP_const8s:
     476         [ #  # ]:          0 :           if (unlikely (data + 8 > end_data))
     477                 :          0 :             goto invalid;
     478                 :            : 
     479         [ #  # ]:          0 :           newloc->number = read_8sbyte_unaligned_inc (&bo, data);
     480                 :          0 :           break;
     481                 :            : 
     482                 :      40088 :         case DW_OP_constu:
     483                 :            :         case DW_OP_plus_uconst:
     484                 :            :         case DW_OP_regx:
     485                 :            :         case DW_OP_piece:
     486                 :            :         case DW_OP_convert:
     487                 :            :         case DW_OP_GNU_convert:
     488                 :            :         case DW_OP_reinterpret:
     489                 :            :         case DW_OP_GNU_reinterpret:
     490                 :            :         case DW_OP_addrx:
     491                 :            :         case DW_OP_GNU_addr_index:
     492                 :            :         case DW_OP_constx:
     493                 :            :         case DW_OP_GNU_const_index:
     494                 :      40088 :           get_uleb128 (newloc->number, data, end_data);
     495                 :      40088 :           break;
     496                 :            : 
     497                 :     196780 :         case DW_OP_consts:
     498                 :            :         case DW_OP_breg0 ... DW_OP_breg31:
     499                 :            :         case DW_OP_fbreg:
     500                 :     196780 :           get_sleb128 (newloc->number, data, end_data);
     501                 :     196780 :           break;
     502                 :            : 
     503                 :          0 :         case DW_OP_bregx:
     504                 :          0 :           get_uleb128 (newloc->number, data, end_data);
     505         [ #  # ]:          0 :           if (unlikely (data >= end_data))
     506                 :          0 :             goto invalid;
     507                 :          0 :           get_sleb128 (newloc->number2, data, end_data);
     508                 :          0 :           break;
     509                 :            : 
     510                 :          0 :         case DW_OP_bit_piece:
     511                 :            :         case DW_OP_regval_type:
     512                 :            :         case DW_OP_GNU_regval_type:
     513                 :          0 :           get_uleb128 (newloc->number, data, end_data);
     514         [ #  # ]:          0 :           if (unlikely (data >= end_data))
     515                 :          0 :             goto invalid;
     516                 :          0 :           get_uleb128 (newloc->number2, data, end_data);
     517                 :          0 :           break;
     518                 :            : 
     519                 :      85260 :         case DW_OP_implicit_value:
     520                 :            :         case DW_OP_entry_value:
     521                 :            :         case DW_OP_GNU_entry_value:
     522                 :            :           /* This cannot be used in a CFI expression.  */
     523         [ -  + ]:      85260 :           if (unlikely (dbg == NULL))
     524                 :          0 :             goto invalid;
     525                 :            : 
     526                 :            :           /* start of block inc. len.  */
     527                 :      85260 :           newloc->number2 = (Dwarf_Word) (uintptr_t) data;
     528                 :      85260 :           get_uleb128 (newloc->number, data, end_data); /* Block length.  */
     529         [ -  + ]:      85260 :           if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number))
     530                 :          0 :             goto invalid;
     531                 :      85260 :           data += newloc->number;            /* Skip the block.  */
     532                 :      85260 :           break;
     533                 :            : 
     534                 :       7352 :         case DW_OP_implicit_pointer:
     535                 :            :         case DW_OP_GNU_implicit_pointer:
     536                 :            :           /* DW_FORM_ref_addr, depends on offset size of CU.  */
     537   [ +  -  -  + ]:      14704 :           if (dbg == NULL || __libdw_read_offset_inc (dbg, sec_index, &data,
     538                 :            :                                                       ref_size,
     539                 :       7352 :                                                       &newloc->number,
     540                 :            :                                                       IDX_debug_info, 0))
     541                 :          0 :             goto invalid;
     542         [ -  + ]:       7352 :           if (unlikely (data >= end_data))
     543                 :          0 :             goto invalid;
     544                 :       7352 :           get_uleb128 (newloc->number2, data, end_data); /* Byte offset.  */
     545                 :       7352 :           break;
     546                 :            : 
     547                 :          2 :         case DW_OP_deref_type:
     548                 :            :         case DW_OP_GNU_deref_type:
     549                 :            :         case DW_OP_xderef_type:
     550         [ -  + ]:          2 :           if (unlikely (data + 1 >= end_data))
     551                 :          0 :             goto invalid;
     552                 :          2 :           newloc->number = *data++;
     553                 :          2 :           get_uleb128 (newloc->number2, data, end_data);
     554                 :          2 :           break;
     555                 :            : 
     556                 :          2 :         case DW_OP_const_type:
     557                 :            :         case DW_OP_GNU_const_type:
     558                 :            :           {
     559                 :          2 :             size_t size;
     560                 :          2 :             get_uleb128 (newloc->number, data, end_data);
     561         [ -  + ]:          2 :             if (unlikely (data >= end_data))
     562                 :          0 :               goto invalid;
     563                 :            : 
     564                 :            :             /* start of block inc. len.  */
     565                 :          2 :             newloc->number2 = (Dwarf_Word) (uintptr_t) data;
     566                 :          2 :             size = *data++;
     567         [ -  + ]:          2 :             if (unlikely ((Dwarf_Word) (end_data - data) < size))
     568                 :          0 :               goto invalid;
     569                 :          2 :             data += size;               /* Skip the block.  */
     570                 :            :           }
     571                 :          2 :           break;
     572                 :            : 
     573                 :          0 :         default:
     574                 :          0 :           goto invalid;
     575                 :            :         }
     576                 :            :     }
     577                 :            : 
     578         [ -  + ]:     834558 :   if (unlikely (n == 0))
     579                 :            :     {
     580                 :            :       /* This is not allowed.
     581                 :            :          It would mean an empty location expression, which we handled
     582                 :            :          already as a special case above.  */
     583                 :          0 :       goto invalid;
     584                 :            :     }
     585                 :            : 
     586         [ -  + ]:     834558 :   if (valuep)
     587                 :            :     {
     588   [ #  #  #  # ]:          0 :       struct loclist *newloc = NEW_LOC ();
     589                 :          0 :       newloc->atom = DW_OP_stack_value;
     590                 :          0 :       newloc->number = 0;
     591                 :          0 :       newloc->number2 = 0;
     592                 :          0 :       newloc->offset = data - block->data;
     593                 :            :     }
     594                 :            : 
     595                 :            :   /* Allocate the array.  */
     596                 :     834558 :   Dwarf_Op *result;
     597         [ +  + ]:     834558 :   if (dbg != NULL)
     598         [ +  + ]:     834556 :     result = libdw_alloc (dbg, Dwarf_Op, sizeof (Dwarf_Op), n);
     599                 :            :   else
     600                 :            :     {
     601                 :          2 :       result = malloc (sizeof *result * n);
     602         [ -  + ]:          2 :       if (result == NULL)
     603                 :            :         {
     604                 :          0 :         nomem:
     605                 :          0 :           __libdw_seterrno (DWARF_E_NOMEM);
     606                 :          0 :           goto returnmem;
     607                 :            :         }
     608                 :            :     }
     609                 :            : 
     610                 :            :   /* Store the result.  */
     611                 :     834558 :   *llbuf = result;
     612                 :     834558 :   *listlen = n;
     613                 :            : 
     614                 :    1229482 :   do
     615                 :            :     {
     616                 :            :       /* We populate the array from the back since the list is backwards.  */
     617                 :    1229482 :       --n;
     618                 :    1229482 :       result[n].atom = loclist->atom;
     619                 :    1229482 :       result[n].number = loclist->number;
     620                 :    1229482 :       result[n].number2 = loclist->number2;
     621                 :    1229482 :       result[n].offset = loclist->offset;
     622                 :            : 
     623         [ +  + ]:    1229482 :       if (result[n].atom == DW_OP_implicit_value)
     624                 :            :         {
     625                 :        606 :           int store = store_implicit_value (dbg, cache, &result[n]);
     626         [ -  + ]:        606 :           if (unlikely (store != 0))
     627                 :            :             {
     628         [ #  # ]:          0 :               if (store < 0)
     629                 :          0 :                 goto invalid;
     630                 :            :               else
     631                 :          0 :                 goto nomem;
     632                 :            :             }
     633                 :            :         }
     634                 :            : 
     635                 :    1229482 :       struct loclist *loc = loclist;
     636                 :    1229482 :       loclist = loclist->next;
     637         [ +  + ]:    1229482 :       if (unlikely (n + 1 > MAX_STACK_LOCS))
     638                 :        274 :         free (loc);
     639                 :            :     }
     640         [ +  + ]:    1229482 :   while (n > 0);
     641                 :            : 
     642                 :            :   /* Insert a record in the search tree so that we can find it again later.  */
     643                 :     834558 :   struct loc_s *newp;
     644         [ +  + ]:     834558 :   if (dbg != NULL)
     645         [ +  + ]:     834556 :     newp = libdw_alloc (dbg, struct loc_s, sizeof (struct loc_s), 1);
     646                 :            :   else
     647                 :            :     {
     648                 :          2 :       newp = malloc (sizeof *newp);
     649         [ -  + ]:          2 :       if (newp == NULL)
     650                 :            :         {
     651                 :          0 :           free (result);
     652                 :          0 :           goto nomem;
     653                 :            :         }
     654                 :            :     }
     655                 :            : 
     656                 :     834558 :   newp->addr = block->data;
     657                 :     834558 :   newp->loc = result;
     658                 :     834558 :   newp->nloc = *listlen;
     659                 :     834558 :   eu_tsearch (newp, cache, loc_compare);
     660                 :            : 
     661                 :            :   /* We did it.  */
     662                 :     834558 :   return 0;
     663                 :            : }
     664                 :            : 
     665                 :            : static int
     666                 :    1298710 : getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
     667                 :            :              Dwarf_Op **llbuf, size_t *listlen, int sec_index)
     668                 :            : {
     669                 :            :   /* Empty location expressions don't have any ops to intern.
     670                 :            :      Note that synthetic empty_cu doesn't have an associated DWARF dbg.  */
     671         [ +  + ]:    1298710 :   if (block->length == 0)
     672                 :            :     {
     673                 :         38 :       *listlen = 0;
     674                 :         38 :       return 0;
     675                 :            :     }
     676                 :            : 
     677                 :    3896016 :   return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order,
     678         [ -  + ]:    2597344 :                                     cu->address_size, (cu->version == 2
     679                 :          0 :                                                        ? cu->address_size
     680                 :    1298672 :                                                        : cu->offset_size),
     681                 :            :                                     &cu->locs_tree, block,
     682                 :            :                                     false, false,
     683                 :            :                                     llbuf, listlen, sec_index);
     684                 :            : }
     685                 :            : 
     686                 :            : int
     687                 :    5387580 : dwarf_getlocation (Dwarf_Attribute *attr, Dwarf_Op **llbuf, size_t *listlen)
     688                 :            : {
     689         [ +  + ]:    5387580 :   if (! attr_ok (attr))
     690                 :            :     return -1;
     691                 :            : 
     692                 :     925166 :   int result = is_constant_offset (attr, llbuf, listlen);
     693         [ +  + ]:     925166 :   if (result != 1)
     694                 :            :     return result; /* Either success 0, or -1 to indicate error.  */
     695                 :            : 
     696                 :            :   /* If it has a block form, it's a single location expression.
     697                 :            :      Except for DW_FORM_data16, which is a 128bit constant.  */
     698         [ -  + ]:     571982 :   if (attr->form == DW_FORM_data16)
     699                 :            :     {
     700                 :          0 :       __libdw_seterrno (DWARF_E_NO_BLOCK);
     701                 :          0 :       return -1;
     702                 :            :     }
     703                 :     571982 :   Dwarf_Block block;
     704         [ +  + ]:     571982 :   if (INTUSE(dwarf_formblock) (attr, &block) != 0)
     705                 :            :     return -1;
     706                 :            : 
     707                 :     252124 :   return getlocation (attr->cu, &block, llbuf, listlen, cu_sec_idx (attr->cu));
     708                 :            : }
     709                 :            : 
     710                 :            : Dwarf_Addr
     711                 :     796866 : __libdw_cu_base_address (Dwarf_CU *cu)
     712                 :            : {
     713         [ +  + ]:     796866 :   if (cu->base_address == (Dwarf_Addr) -1)
     714                 :            :     {
     715                 :       4558 :       Dwarf_Addr base;
     716                 :            : 
     717                 :            :       /* Fetch the CU's base address.  */
     718                 :       4558 :       Dwarf_Die cudie = CUDIE (cu);
     719                 :            : 
     720                 :            :       /* Find the base address of the compilation unit.  It will
     721                 :            :          normally be specified by DW_AT_low_pc.  In DWARF-3 draft 4,
     722                 :            :          the base address could be overridden by DW_AT_entry_pc.  It's
     723                 :            :          been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc
     724                 :            :          for compilation units with discontinuous ranges.  */
     725                 :       4558 :       Dwarf_Attribute attr_mem;
     726         [ +  + ]:       4558 :       if (INTUSE(dwarf_lowpc) (&cudie, &base) != 0
     727         [ +  - ]:         18 :           && INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (&cudie,
     728                 :            :                                                          DW_AT_entry_pc,
     729                 :            :                                                          &attr_mem),
     730                 :            :                                      &base) != 0)
     731                 :            :         {
     732                 :            :           /* The compiler provided no base address when it should
     733                 :            :              have.  Buggy GCC does this when it used absolute
     734                 :            :              addresses in the location list and no DW_AT_ranges.  */
     735                 :         18 :            base = 0;
     736                 :            :         }
     737                 :       4558 :       cu->base_address = base;
     738                 :            :     }
     739                 :            : 
     740                 :     796866 :   return cu->base_address;
     741                 :            : }
     742                 :            : 
     743                 :            : static int
     744                 :     782962 : initial_offset (Dwarf_Attribute *attr, ptrdiff_t *offset)
     745                 :            : {
     746                 :    1565924 :   size_t secidx = (attr->cu->version < 5
     747         [ +  + ]:     782962 :                    ? IDX_debug_loc : IDX_debug_loclists);
     748                 :            : 
     749                 :     782962 :   Dwarf_Word start_offset;
     750         [ +  + ]:     782962 :   if (attr->form == DW_FORM_loclistx)
     751                 :            :     {
     752                 :        218 :       Dwarf_Word idx;
     753                 :        218 :       Dwarf_CU *cu = attr->cu;
     754                 :        218 :       const unsigned char *datap = attr->valp;
     755                 :        218 :       const unsigned char *endp = cu->endp;
     756         [ -  + ]:        218 :       if (datap >= endp)
     757                 :            :         {
     758                 :          0 :           __libdw_seterrno (DWARF_E_INVALID_DWARF);
     759                 :          0 :           return -1;
     760                 :            :         }
     761                 :        218 :       get_uleb128 (idx, datap, endp);
     762                 :            : 
     763                 :        218 :       Elf_Data *data = cu->dbg->sectiondata[secidx];
     764   [ -  +  -  - ]:        218 :       if (data == NULL && cu->unit_type == DW_UT_split_compile)
     765                 :            :         {
     766                 :          0 :           cu = __libdw_find_split_unit (cu);
     767         [ #  # ]:          0 :           if (cu != NULL)
     768                 :          0 :             data = cu->dbg->sectiondata[secidx];
     769                 :            :         }
     770                 :            : 
     771         [ #  # ]:          0 :       if (data == NULL)
     772                 :            :         {
     773         [ #  # ]:          0 :           __libdw_seterrno (secidx == IDX_debug_loc
     774                 :            :                             ? DWARF_E_NO_DEBUG_LOC
     775                 :            :                             : DWARF_E_NO_DEBUG_LOCLISTS);
     776                 :          0 :           return -1;
     777                 :            :         }
     778                 :            : 
     779                 :        218 :       Dwarf_Off loc_base_off = __libdw_cu_locs_base (cu);
     780                 :            : 
     781                 :            :       /* The section should at least contain room for one offset.  */
     782                 :        218 :       size_t sec_size = cu->dbg->sectiondata[secidx]->d_size;
     783                 :        218 :       size_t offset_size = cu->offset_size;
     784         [ -  + ]:        218 :       if (offset_size > sec_size)
     785                 :            :         {
     786                 :          0 :         invalid_offset:
     787                 :          0 :           __libdw_seterrno (DWARF_E_INVALID_OFFSET);
     788                 :          0 :           return -1;
     789                 :            :         }
     790                 :            : 
     791                 :            :       /* And the base offset should be at least inside the section.  */
     792         [ -  + ]:        218 :       if (loc_base_off > (sec_size - offset_size))
     793                 :          0 :         goto invalid_offset;
     794                 :            : 
     795                 :        218 :       size_t max_idx = (sec_size - offset_size - loc_base_off) / offset_size;
     796         [ -  + ]:        218 :       if (idx > max_idx)
     797                 :          0 :         goto invalid_offset;
     798                 :            : 
     799                 :        218 :       datap = (cu->dbg->sectiondata[secidx]->d_buf
     800                 :        218 :                + loc_base_off + (idx * offset_size));
     801         [ +  - ]:        218 :       if (offset_size == 4)
     802         [ -  + ]:        218 :         start_offset = read_4ubyte_unaligned (cu->dbg, datap);
     803                 :            :       else
     804         [ #  # ]:          0 :         start_offset = read_8ubyte_unaligned (cu->dbg, datap);
     805                 :            : 
     806                 :        218 :       start_offset += loc_base_off;
     807                 :            :     }
     808                 :            :   else
     809                 :            :     {
     810   [ +  +  +  + ]:    1565064 :       if (__libdw_formptr (attr, secidx,
     811                 :            :                            (secidx == IDX_debug_loc
     812                 :            :                             ? DWARF_E_NO_DEBUG_LOC
     813                 :            :                             : DWARF_E_NO_DEBUG_LOCLISTS),
     814                 :            :                             NULL, &start_offset) == NULL)
     815                 :     190398 :         return -1;
     816                 :            : 
     817                 :     592346 :       Dwarf_Off loc_off;
     818         [ +  - ]:     592346 :       if (INTUSE(dwarf_cu_dwp_section_info) (attr->cu, DW_SECT_LOCLISTS,
     819                 :            :                                              &loc_off, NULL) != 0)
     820                 :            :         return -1;
     821                 :     592346 :       start_offset += loc_off;
     822                 :            :     }
     823                 :            : 
     824                 :     592564 :   *offset = start_offset;
     825                 :     592564 :   return 0;
     826                 :            : }
     827                 :            : 
     828                 :            : static ptrdiff_t
     829                 :    1175414 : getlocations_addr (Dwarf_Attribute *attr, ptrdiff_t offset,
     830                 :            :                    Dwarf_Addr *basep, Dwarf_Addr *startp, Dwarf_Addr *endp,
     831                 :            :                    Dwarf_Addr address, const Elf_Data *locs, Dwarf_Op **expr,
     832                 :            :                    size_t *exprlen)
     833                 :            : {
     834                 :    1175414 :   Dwarf_CU *cu = attr->cu;
     835                 :    1175414 :   Dwarf *dbg = cu->dbg;
     836         [ +  + ]:    1175414 :   size_t secidx = cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
     837                 :    1175414 :   const unsigned char *readp = locs->d_buf + offset;
     838                 :    1175414 :   const unsigned char *readendp = locs->d_buf + locs->d_size;
     839                 :            : 
     840                 :    4088812 :   Dwarf_Addr begin;
     841                 :    4088812 :   Dwarf_Addr end;
     842                 :            : 
     843                 :            :  next:
     844   [ +  -  +  + ]:    4088812 :   switch (__libdw_read_begin_end_pair_inc (cu, secidx,
     845                 :            :                                            &readp, readendp,
     846                 :    4088812 :                                            cu->address_size,
     847                 :            :                                            &begin, &end, basep))
     848                 :            :     {
     849                 :            :     case 0: /* got location range. */
     850                 :    3897614 :       break;
     851                 :      61150 :     case 1: /* base address setup. */
     852                 :      61150 :       goto next;
     853                 :            :     case 2: /* end of loclist */
     854                 :            :       return 0;
     855                 :            :     default: /* error */
     856                 :            :       return -1;
     857                 :            :     }
     858                 :            : 
     859                 :            :   /* We have a location expression.  */
     860                 :    3897614 :   Dwarf_Block block;
     861         [ +  + ]:    3897614 :   if (secidx == IDX_debug_loc)
     862                 :            :     {
     863         [ -  + ]:        856 :       if (readendp - readp < 2)
     864                 :            :         {
     865                 :          0 :         invalid:
     866                 :          0 :           __libdw_seterrno (DWARF_E_INVALID_DWARF);
     867                 :          0 :           return -1;
     868                 :            :         }
     869         [ -  + ]:        856 :       block.length = read_2ubyte_unaligned_inc (dbg, readp);
     870                 :            :     }
     871                 :            :   else
     872                 :            :     {
     873         [ -  + ]:    3896758 :       if (readendp - readp < 1)
     874                 :          0 :         goto invalid;
     875                 :    3896758 :       get_uleb128 (block.length, readp, readendp);
     876                 :            :     }
     877                 :    3897614 :   block.data = (unsigned char *) readp;
     878         [ -  + ]:    3897614 :   if (readendp - readp < (ptrdiff_t) block.length)
     879                 :          0 :     goto invalid;
     880                 :    3897614 :   readp += block.length;
     881                 :            : 
     882                 :            :   /* Note these addresses include any base (if necessary) already.  */
     883                 :    3897614 :   *startp = begin;
     884                 :    3897614 :   *endp = end;
     885                 :            : 
     886                 :            :   /* If address is minus one we want them all, otherwise only matching.  */
     887   [ +  +  +  +  :    3897614 :   if (address != (Dwarf_Word) -1 && (address < *startp || address >= *endp))
                   +  + ]
     888                 :    2852248 :     goto next;
     889                 :            : 
     890         [ -  + ]:    1045366 :   if (getlocation (cu, &block, expr, exprlen, secidx) != 0)
     891                 :            :     return -1;
     892                 :            : 
     893                 :    1045366 :   return readp - (unsigned char *) locs->d_buf;
     894                 :            : }
     895                 :            : 
     896                 :            : int
     897                 :     464324 : dwarf_getlocation_addr (Dwarf_Attribute *attr, Dwarf_Addr address,
     898                 :            :                         Dwarf_Op **llbufs, size_t *listlens, size_t maxlocs)
     899                 :            : {
     900         [ -  + ]:     464324 :   if (! attr_ok (attr))
     901                 :            :     return -1;
     902                 :            : 
     903         [ -  + ]:     464324 :   if (llbufs == NULL)
     904                 :          0 :     maxlocs = SIZE_MAX;
     905                 :            : 
     906                 :            :   /* If it has a block form, it's a single location expression.
     907                 :            :      Except for DW_FORM_data16, which is a 128bit constant.  */
     908                 :     464324 :   Dwarf_Block block;
     909         [ +  - ]:     464324 :   if (attr->form != DW_FORM_data16
     910         [ +  + ]:     464324 :       && INTUSE(dwarf_formblock) (attr, &block) == 0)
     911                 :            :     {
     912         [ +  - ]:       1220 :       if (maxlocs == 0)
     913                 :            :         return 0;
     914   [ +  -  -  + ]:       2440 :       if (llbufs != NULL &&
     915                 :       1220 :           getlocation (attr->cu, &block, &llbufs[0], &listlens[0],
     916                 :       1220 :                        cu_sec_idx (attr->cu)) != 0)
     917                 :            :         return -1;
     918                 :       1220 :       return listlens[0] == 0 ? 0 : 1;
     919                 :            :     }
     920                 :            : 
     921         [ +  - ]:     463104 :   if (attr->form != DW_FORM_data16)
     922                 :            :     {
     923                 :     463104 :       int error = INTUSE(dwarf_errno) ();
     924         [ -  + ]:     463104 :       if (unlikely (error != DWARF_E_NO_BLOCK))
     925                 :            :         {
     926                 :          0 :           __libdw_seterrno (error);
     927                 :          0 :           return -1;
     928                 :            :         }
     929                 :            :     }
     930                 :            : 
     931                 :            :   /* If is_constant_offset is successful, we are done with 1 result.  */
     932                 :     463104 :   int result = is_constant_offset (attr, llbufs, listlens);
     933         [ -  + ]:     463104 :   if (result != 1)
     934         [ #  # ]:          0 :     return result ?: 1;
     935                 :            : 
     936                 :     463104 :   Dwarf_Addr base, start, end;
     937                 :     463104 :   Dwarf_Op *expr;
     938                 :     463104 :   size_t expr_len;
     939                 :     463104 :   ptrdiff_t off = 0;
     940                 :     463104 :   size_t got = 0;
     941                 :            : 
     942                 :            :   /* This is a true loclistptr, fetch the initial base address and offset.  */
     943                 :     463104 :   base = __libdw_cu_base_address (attr->cu);
     944         [ -  + ]:     463104 :   if (base == (Dwarf_Addr) -1)
     945                 :            :     return -1;
     946                 :            : 
     947         [ -  + ]:     463104 :   if (initial_offset (attr, &off) != 0)
     948                 :            :     return -1;
     949                 :            : 
     950         [ +  + ]:     463104 :   size_t secidx = attr->cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
     951                 :     463104 :   const Elf_Data *d = attr->cu->dbg->sectiondata[secidx];
     952                 :            : 
     953                 :     463104 :   while (got < maxlocs
     954   [ +  +  +  + ]:     925620 :          && (off = getlocations_addr (attr, off, &base, &start, &end,
     955                 :            :                                       address, d, &expr, &expr_len)) > 0)
     956                 :            :     {
     957                 :            :       /* This one matches the address.  */
     958         [ +  - ]:     462516 :       if (llbufs != NULL)
     959                 :            :         {
     960                 :     462516 :           llbufs[got] = expr;
     961                 :     462516 :           listlens[got] = expr_len;
     962                 :            :         }
     963                 :     462516 :       ++got;
     964                 :            :     }
     965                 :            : 
     966                 :            :   /* We might stop early, so off can be zero or positive on success.  */
     967         [ -  + ]:     463104 :   if (off < 0)
     968                 :            :     return -1;
     969                 :            : 
     970                 :     463104 :   return got;
     971                 :            : }
     972                 :            : 
     973                 :            : ptrdiff_t
     974                 :    5365122 : dwarf_getlocations (Dwarf_Attribute *attr, ptrdiff_t offset, Dwarf_Addr *basep,
     975                 :            :                     Dwarf_Addr *startp, Dwarf_Addr *endp, Dwarf_Op **expr,
     976                 :            :                     size_t *exprlen)
     977                 :            : {
     978         [ +  + ]:    5365122 :   if (! attr_ok (attr))
     979                 :            :     return -1;
     980                 :            : 
     981                 :            :   /* 1 is an invalid offset, meaning no more locations. */
     982         [ +  - ]:     902708 :   if (offset == 1)
     983                 :            :     return 0;
     984                 :            : 
     985         [ +  + ]:     902708 :   if (offset == 0)
     986                 :            :     {
     987                 :            :       /* If it has a block form, it's a single location expression.
     988                 :            :          Except for DW_FORM_data16, which is a 128bit constant.  */
     989                 :     319858 :       Dwarf_Block block;
     990         [ +  - ]:     319858 :       if (attr->form != DW_FORM_data16
     991         [ -  + ]:     319858 :           && INTUSE(dwarf_formblock) (attr, &block) == 0)
     992                 :            :         {
     993         [ #  # ]:          0 :           if (getlocation (attr->cu, &block, expr, exprlen,
     994                 :          0 :                            cu_sec_idx (attr->cu)) != 0)
     995                 :     190398 :             return -1;
     996                 :            : 
     997                 :            :           /* This is the one and only location covering everything. */
     998                 :          0 :           *startp = 0;
     999                 :          0 :           *endp = -1;
    1000                 :          0 :           return 1;
    1001                 :            :         }
    1002                 :            : 
    1003         [ +  - ]:     319858 :       if (attr->form != DW_FORM_data16)
    1004                 :            :         {
    1005                 :     319858 :           int error = INTUSE(dwarf_errno) ();
    1006         [ -  + ]:     319858 :           if (unlikely (error != DWARF_E_NO_BLOCK))
    1007                 :            :             {
    1008                 :          0 :               __libdw_seterrno (error);
    1009                 :          0 :               return -1;
    1010                 :            :             }
    1011                 :            :         }
    1012                 :            : 
    1013                 :     319858 :       int result = is_constant_offset (attr, expr, exprlen);
    1014         [ -  + ]:     319858 :       if (result != 1)
    1015                 :            :         {
    1016         [ #  # ]:          0 :           if (result == 0)
    1017                 :            :             {
    1018                 :            :               /* This is the one and only location covering everything. */
    1019                 :          0 :               *startp = 0;
    1020                 :          0 :               *endp = -1;
    1021                 :          0 :               return 1;
    1022                 :            :             }
    1023                 :          0 :           return result; /* Something bad, dwarf_errno has been set.  */
    1024                 :            :         }
    1025                 :            : 
    1026                 :            :       /* We must be looking at a true loclistptr, fetch the initial
    1027                 :            :          base address and offset.  */
    1028                 :     319858 :       *basep = __libdw_cu_base_address (attr->cu);
    1029         [ +  - ]:     319858 :       if (*basep == (Dwarf_Addr) -1)
    1030                 :            :         return -1;
    1031                 :            : 
    1032         [ +  + ]:     319858 :       if (initial_offset (attr, &offset) != 0)
    1033                 :            :         return -1;
    1034                 :            :     }
    1035                 :            : 
    1036         [ +  + ]:     712310 :   size_t secidx = attr->cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
    1037                 :     712310 :   const Elf_Data *d = attr->cu->dbg->sectiondata[secidx];
    1038                 :            : 
    1039                 :     712310 :   return getlocations_addr (attr, offset, basep, startp, endp,
    1040                 :            :                             (Dwarf_Word) -1, d, expr, exprlen);
    1041                 :            : }

Generated by: LCOV version 1.16