LCOV - code coverage report
Current view: top level - libdw - dwarf_getlocation.c (source / functions) Hit Total Coverage
Test: elfutils-0.193 Lines: 329 441 74.6 %
Date: 2025-06-03 13:14:14 Functions: 13 13 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 185 316 58.5 %

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

Generated by: LCOV version 1.16