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

Generated by: LCOV version 1.13