LCOV - code coverage report
Current view: top level - libdw - dwarf_getlocation.c (source / functions) Hit Total Coverage
Test: elfutils-0.190 Lines: 320 431 74.2 %
Date: 2023-12-21 21:54:50 Functions: 13 13 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 184 314 58.6 %

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

Generated by: LCOV version 1.16