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

Generated by: LCOV version 1.13