LCOV - code coverage report
Current view: top level - libdw - dwarf_getlocation.c (source / functions) Hit Total Coverage
Test: elfutils-0.183 Lines: 289 422 68.5 %
Date: 2021-02-07 19:08:58 Functions: 12 13 92.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 164 310 52.9 %

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

Generated by: LCOV version 1.13