LCOV - code coverage report
Current view: top level - libdw - dwarf_getlocation.c (source / functions) Hit Total Coverage
Test: elfutils-0.175 Lines: 293 370 79.2 %
Date: 2018-11-16 13:02:39 Functions: 13 13 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13