LCOV - code coverage report
Current view: top level - elfutils/libdw - dwarf_getlocation.c (source / functions) Hit Total Coverage
Test: lcov.out Lines: 70 226 31.0 %
Date: 2012-10-31 Functions: 6 9 66.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 29 222 13.1 %

           Branch data     Line data    Source code
       1                 :            : /* Return location expression list.
       2                 :            :    Copyright (C) 2000-2010 Red Hat, Inc.
       3                 :            :    This file is part of elfutils.
       4                 :            :    Written by Ulrich Drepper <drepper@redhat.com>, 2000.
       5                 :            : 
       6                 :            :    This file is free software; you can redistribute it and/or modify
       7                 :            :    it under the terms of either
       8                 :            : 
       9                 :            :      * the GNU Lesser General Public License as published by the Free
      10                 :            :        Software Foundation; either version 3 of the License, or (at
      11                 :            :        your option) any later version
      12                 :            : 
      13                 :            :    or
      14                 :            : 
      15                 :            :      * the GNU General Public License as published by the Free
      16                 :            :        Software Foundation; either version 2 of the License, or (at
      17                 :            :        your option) any later version
      18                 :            : 
      19                 :            :    or both in parallel, as here.
      20                 :            : 
      21                 :            :    elfutils is distributed in the hope that it will be useful, but
      22                 :            :    WITHOUT ANY WARRANTY; without even the implied warranty of
      23                 :            :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      24                 :            :    General Public License for more details.
      25                 :            : 
      26                 :            :    You should have received copies of the GNU General Public License and
      27                 :            :    the GNU Lesser General Public License along with this program.  If
      28                 :            :    not, see <http://www.gnu.org/licenses/>.  */
      29                 :            : 
      30                 :            : #ifdef HAVE_CONFIG_H
      31                 :            : # include <config.h>
      32                 :            : #endif
      33                 :            : 
      34                 :            : #include <dwarf.h>
      35                 :            : #include <search.h>
      36                 :            : #include <stdlib.h>
      37                 :            : #include <assert.h>
      38                 :            : 
      39                 :            : #include <libdwP.h>
      40                 :            : 
      41                 :            : 
      42                 :            : static bool
      43                 :       7080 : attr_ok (Dwarf_Attribute *attr)
      44                 :            : {
      45         [ +  - ]:       7080 :   if (attr == NULL)
      46                 :            :     return false;
      47                 :            : 
      48                 :            :   /* Must be one of the attributes listed below.  */
      49         [ -  + ]:       7080 :   switch (attr->code)
      50                 :            :     {
      51                 :            :     case DW_AT_location:
      52                 :            :     case DW_AT_data_member_location:
      53                 :            :     case DW_AT_vtable_elem_location:
      54                 :            :     case DW_AT_string_length:
      55                 :            :     case DW_AT_use_location:
      56                 :            :     case DW_AT_frame_base:
      57                 :            :     case DW_AT_return_addr:
      58                 :            :     case DW_AT_static_link:
      59                 :            :       break;
      60                 :            : 
      61                 :            :     default:
      62                 :          0 :       __libdw_seterrno (DWARF_E_NO_LOCLIST);
      63                 :       7080 :       return false;
      64                 :            :     }
      65                 :            : 
      66                 :            :   return true;
      67                 :            : }
      68                 :            : 
      69                 :            : 
      70                 :            : struct loclist
      71                 :            : {
      72                 :            :   uint8_t atom;
      73                 :            :   Dwarf_Word number;
      74                 :            :   Dwarf_Word number2;
      75                 :            :   Dwarf_Word offset;
      76                 :            :   struct loclist *next;
      77                 :            : };
      78                 :            : 
      79                 :            : 
      80                 :            : static int
      81                 :      34584 : loc_compare (const void *p1, const void *p2)
      82                 :            : {
      83                 :      34584 :   const struct loc_s *l1 = (const struct loc_s *) p1;
      84                 :      34584 :   const struct loc_s *l2 = (const struct loc_s *) p2;
      85                 :            : 
      86         [ +  - ]:      34584 :   if ((uintptr_t) l1->addr < (uintptr_t) l2->addr)
      87                 :            :     return -1;
      88         [ -  + ]:      34584 :   if ((uintptr_t) l1->addr > (uintptr_t) l2->addr)
      89                 :            :     return 1;
      90                 :            : 
      91                 :      34584 :   return 0;
      92                 :            : }
      93                 :            : 
      94                 :            : /* For each DW_OP_implicit_value, we store a special entry in the cache.
      95                 :            :    This points us directly to the block data for later fetching.  */
      96                 :            : static void
      97                 :          0 : store_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op,
      98                 :            :                       unsigned char *data)
      99                 :            : {
     100         [ #  # ]:          0 :   struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s,
     101                 :            :                                            sizeof (struct loc_block_s), 1);
     102                 :          0 :   block->addr = op;
     103                 :          0 :   block->data = data + op->number2;
     104                 :          0 :   block->length = op->number;
     105                 :          0 :   (void) tsearch (block, cache, loc_compare);
     106                 :          0 : }
     107                 :            : 
     108                 :            : int
     109                 :          0 : dwarf_getlocation_implicit_value (attr, op, return_block)
     110                 :            :      Dwarf_Attribute *attr;
     111                 :            :      const Dwarf_Op *op;
     112                 :            :      Dwarf_Block *return_block;
     113                 :            : {
     114         [ #  # ]:          0 :   if (attr == NULL)
     115                 :            :     return -1;
     116                 :            : 
     117                 :          0 :   struct loc_block_s fake = { .addr = (void *) op };
     118                 :          0 :   struct loc_block_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
     119         [ #  # ]:          0 :   if (unlikely (found == NULL))
     120                 :            :     {
     121                 :          0 :       __libdw_seterrno (DWARF_E_NO_BLOCK);
     122                 :            :       return -1;
     123                 :            :     }
     124                 :            : 
     125                 :          0 :   return_block->length = (*found)->length;
     126                 :          0 :   return_block->data = (*found)->data;
     127                 :            :   return 0;
     128                 :            : }
     129                 :            : 
     130                 :            : /* DW_AT_data_member_location can be a constant as well as a loclistptr.
     131                 :            :    Only data[48] indicate a loclistptr.  */
     132                 :            : static int
     133                 :       7080 : check_constant_offset (Dwarf_Attribute *attr,
     134                 :            :                        Dwarf_Op **llbuf, size_t *listlen)
     135                 :            : {
     136         [ -  + ]:       7080 :   if (attr->code != DW_AT_data_member_location)
     137                 :            :     return 1;
     138                 :            : 
     139         [ #  # ]:          0 :   switch (attr->form)
     140                 :            :     {
     141                 :            :       /* Punt for any non-constant form.  */
     142                 :            :     default:
     143                 :            :       return 1;
     144                 :            : 
     145                 :            :     case DW_FORM_data1:
     146                 :            :     case DW_FORM_data2:
     147                 :            :     case DW_FORM_data4:
     148                 :            :     case DW_FORM_data8:
     149                 :            :     case DW_FORM_sdata:
     150                 :            :     case DW_FORM_udata:
     151                 :            :       break;
     152                 :            :     }
     153                 :            : 
     154                 :            :   /* Check whether we already cached this location.  */
     155                 :          0 :   struct loc_s fake = { .addr = attr->valp };
     156                 :          0 :   struct loc_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
     157                 :            : 
     158         [ #  # ]:          0 :   if (found == NULL)
     159                 :            :     {
     160                 :            :       Dwarf_Word offset;
     161         [ #  # ]:          0 :       if (INTUSE(dwarf_formudata) (attr, &offset) != 0)
     162                 :            :         return -1;
     163                 :            : 
     164         [ #  # ]:          0 :       Dwarf_Op *result = libdw_alloc (attr->cu->dbg,
     165                 :            :                                       Dwarf_Op, sizeof (Dwarf_Op), 1);
     166                 :            : 
     167                 :          0 :       result->atom = DW_OP_plus_uconst;
     168                 :          0 :       result->number = offset;
     169                 :          0 :       result->number2 = 0;
     170                 :          0 :       result->offset = 0;
     171                 :            : 
     172                 :            :       /* Insert a record in the search tree so we can find it again later.  */
     173         [ #  # ]:          0 :       struct loc_s *newp = libdw_alloc (attr->cu->dbg,
     174                 :            :                                         struct loc_s, sizeof (struct loc_s),
     175                 :            :                                         1);
     176                 :          0 :       newp->addr = attr->valp;
     177                 :          0 :       newp->loc = result;
     178                 :          0 :       newp->nloc = 1;
     179                 :            : 
     180                 :          0 :       found = tsearch (newp, &attr->cu->locs, loc_compare);
     181                 :            :     }
     182                 :            : 
     183         [ #  # ]:          0 :   assert ((*found)->nloc == 1);
     184                 :            : 
     185         [ #  # ]:          0 :   if (llbuf != NULL)
     186                 :            :     {
     187                 :          0 :       *llbuf = (*found)->loc;
     188                 :       7080 :       *listlen = 1;
     189                 :            :     }
     190                 :            : 
     191                 :            :   return 0;
     192                 :            : }
     193                 :            : 
     194                 :            : int
     195                 :            : internal_function
     196                 :       7080 : __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
     197                 :            :                            unsigned int address_size, unsigned int ref_size,
     198                 :            :                            void **cache, const Dwarf_Block *block,
     199                 :            :                            bool cfap, bool valuep,
     200                 :            :                            Dwarf_Op **llbuf, size_t *listlen, int sec_index)
     201                 :            : {
     202                 :            :   /* Check whether we already looked at this list.  */
     203                 :       7080 :   struct loc_s fake = { .addr = block->data };
     204                 :       7080 :   struct loc_s **found = tfind (&fake, cache, loc_compare);
     205         [ -  + ]:       7080 :   if (found != NULL)
     206                 :            :     {
     207                 :            :       /* We already saw it.  */
     208                 :          0 :       *llbuf = (*found)->loc;
     209                 :          0 :       *listlen = (*found)->nloc;
     210                 :            : 
     211         [ #  # ]:          0 :       if (valuep)
     212                 :            :         {
     213         [ #  # ]:          0 :           assert (*listlen > 1);
     214         [ #  # ]:          0 :           assert ((*llbuf)[*listlen - 1].atom == DW_OP_stack_value);
     215                 :            :         }
     216                 :            : 
     217                 :            :       return 0;
     218                 :            :     }
     219                 :            : 
     220                 :       7080 :   const unsigned char *data = block->data;
     221                 :       7080 :   const unsigned char *const end_data = data + block->length;
     222                 :            : 
     223                 :       7080 :   const struct { bool other_byte_order; } bo = { other_byte_order };
     224                 :            : 
     225                 :       7080 :   struct loclist *loclist = NULL;
     226                 :       7080 :   unsigned int n = 0;
     227                 :            : 
     228         [ -  + ]:       7080 :   if (cfap)
     229                 :            :     {
     230                 :            :       /* Synthesize the operation to push the CFA before the expression.  */
     231                 :            :       struct loclist *newloc;
     232                 :          0 :       newloc = (struct loclist *) alloca (sizeof (struct loclist));
     233                 :          0 :       newloc->atom = DW_OP_call_frame_cfa;
     234                 :          0 :       newloc->number = 0;
     235                 :          0 :       newloc->number2 = 0;
     236                 :          0 :       newloc->offset = -1;
     237                 :          0 :       newloc->next = loclist;
     238                 :          0 :       loclist = newloc;
     239                 :       7080 :       ++n;
     240                 :            :     }
     241                 :            : 
     242                 :            :   /* Decode the opcodes.  It is possible in some situations to have a
     243                 :            :      block of size zero.  */
     244         [ +  + ]:      14412 :   while (data < end_data)
     245                 :            :     {
     246                 :            :       struct loclist *newloc;
     247                 :       7332 :       newloc = (struct loclist *) alloca (sizeof (struct loclist));
     248                 :       7332 :       newloc->number = 0;
     249                 :       7332 :       newloc->number2 = 0;
     250                 :       7332 :       newloc->offset = data - block->data;
     251                 :       7332 :       newloc->next = loclist;
     252                 :       7332 :       loclist = newloc;
     253                 :       7332 :       ++n;
     254                 :            : 
     255   [ +  -  -  -  :       7332 :       switch ((newloc->atom = *data++))
          -  -  -  -  -  
          +  -  -  -  -  
          -  -  -  -  -  
                      + ]
     256                 :            :         {
     257                 :            :         case DW_OP_addr:
     258                 :            :           /* Address, depends on address size of CU.  */
     259         [ +  - ]:       6828 :           if (__libdw_read_address_inc (dbg, sec_index, &data,
     260                 :       6828 :                                         address_size, &newloc->number))
     261                 :            :             return -1;
     262                 :            :           break;
     263                 :            : 
     264                 :            :         case DW_OP_call_ref:
     265                 :            :           /* DW_FORM_ref_addr, depends on offset size of CU.  */
     266         [ #  # ]:          0 :           if (__libdw_read_offset_inc (dbg, sec_index, &data, ref_size,
     267                 :          0 :                                        &newloc->number, IDX_debug_info, 0))
     268                 :            :             return -1;
     269                 :            :           break;
     270                 :            : 
     271                 :            :         case DW_OP_deref:
     272                 :            :         case DW_OP_dup:
     273                 :            :         case DW_OP_drop:
     274                 :            :         case DW_OP_over:
     275                 :            :         case DW_OP_swap:
     276                 :            :         case DW_OP_rot:
     277                 :            :         case DW_OP_xderef:
     278                 :            :         case DW_OP_abs:
     279                 :            :         case DW_OP_and:
     280                 :            :         case DW_OP_div:
     281                 :            :         case DW_OP_minus:
     282                 :            :         case DW_OP_mod:
     283                 :            :         case DW_OP_mul:
     284                 :            :         case DW_OP_neg:
     285                 :            :         case DW_OP_not:
     286                 :            :         case DW_OP_or:
     287                 :            :         case DW_OP_plus:
     288                 :            :         case DW_OP_shl:
     289                 :            :         case DW_OP_shr:
     290                 :            :         case DW_OP_shra:
     291                 :            :         case DW_OP_xor:
     292                 :            :         case DW_OP_eq:
     293                 :            :         case DW_OP_ge:
     294                 :            :         case DW_OP_gt:
     295                 :            :         case DW_OP_le:
     296                 :            :         case DW_OP_lt:
     297                 :            :         case DW_OP_ne:
     298                 :            :         case DW_OP_lit0 ... DW_OP_lit31:
     299                 :            :         case DW_OP_reg0 ... DW_OP_reg31:
     300                 :            :         case DW_OP_nop:
     301                 :            :         case DW_OP_push_object_address:
     302                 :            :         case DW_OP_call_frame_cfa:
     303                 :            :         case DW_OP_form_tls_address:
     304                 :            :         case DW_OP_GNU_push_tls_address:
     305                 :            :         case DW_OP_stack_value:
     306                 :            :           /* No operand.  */
     307                 :            :           break;
     308                 :            : 
     309                 :            :         case DW_OP_const1u:
     310                 :            :         case DW_OP_pick:
     311                 :            :         case DW_OP_deref_size:
     312                 :            :         case DW_OP_xderef_size:
     313         [ #  # ]:          0 :           if (unlikely (data >= end_data))
     314                 :            :             {
     315                 :            :             invalid:
     316                 :          0 :               __libdw_seterrno (DWARF_E_INVALID_DWARF);
     317                 :            :               return -1;
     318                 :            :             }
     319                 :            : 
     320                 :          0 :           newloc->number = *data++;
     321                 :          0 :           break;
     322                 :            : 
     323                 :            :         case DW_OP_const1s:
     324         [ #  # ]:          0 :           if (unlikely (data >= end_data))
     325                 :            :             goto invalid;
     326                 :            : 
     327                 :          0 :           newloc->number = *((int8_t *) data);
     328                 :          0 :           ++data;
     329                 :          0 :           break;
     330                 :            : 
     331                 :            :         case DW_OP_const2u:
     332         [ #  # ]:          0 :           if (unlikely (data + 2 > end_data))
     333                 :            :             goto invalid;
     334                 :            : 
     335 [ #  # ][ #  # ]:          0 :           newloc->number = read_2ubyte_unaligned_inc (&bo, data);
     336                 :          0 :           break;
     337                 :            : 
     338                 :            :         case DW_OP_const2s:
     339                 :            :         case DW_OP_skip:
     340                 :            :         case DW_OP_bra:
     341                 :            :         case DW_OP_call2:
     342         [ #  # ]:          0 :           if (unlikely (data + 2 > end_data))
     343                 :            :             goto invalid;
     344                 :            : 
     345 [ #  # ][ #  # ]:          0 :           newloc->number = read_2sbyte_unaligned_inc (&bo, data);
     346                 :          0 :           break;
     347                 :            : 
     348                 :            :         case DW_OP_const4u:
     349         [ #  # ]:          0 :           if (unlikely (data + 4 > end_data))
     350                 :            :             goto invalid;
     351                 :            : 
     352 [ #  # ][ #  # ]:          0 :           newloc->number = read_4ubyte_unaligned_inc (&bo, data);
     353                 :          0 :           break;
     354                 :            : 
     355                 :            :         case DW_OP_const4s:
     356                 :            :         case DW_OP_call4:
     357                 :            :         case DW_OP_GNU_parameter_ref:
     358         [ #  # ]:          0 :           if (unlikely (data + 4 > end_data))
     359                 :            :             goto invalid;
     360                 :            : 
     361 [ #  # ][ #  # ]:          0 :           newloc->number = read_4sbyte_unaligned_inc (&bo, data);
     362                 :          0 :           break;
     363                 :            : 
     364                 :            :         case DW_OP_const8u:
     365         [ -  + ]:        252 :           if (unlikely (data + 8 > end_data))
     366                 :            :             goto invalid;
     367                 :            : 
     368 [ -  + ][ #  # ]:        252 :           newloc->number = read_8ubyte_unaligned_inc (&bo, data);
     369                 :        252 :           break;
     370                 :            : 
     371                 :            :         case DW_OP_const8s:
     372         [ #  # ]:          0 :           if (unlikely (data + 8 > end_data))
     373                 :            :             goto invalid;
     374                 :            : 
     375 [ #  # ][ #  # ]:          0 :           newloc->number = read_8sbyte_unaligned_inc (&bo, data);
     376                 :          0 :           break;
     377                 :            : 
     378                 :            :         case DW_OP_constu:
     379                 :            :         case DW_OP_plus_uconst:
     380                 :            :         case DW_OP_regx:
     381                 :            :         case DW_OP_piece:
     382                 :            :         case DW_OP_GNU_convert:
     383                 :            :         case DW_OP_GNU_reinterpret:
     384                 :            :           /* XXX Check size.  */
     385         [ #  # ]:          0 :           get_uleb128 (newloc->number, data);
     386                 :            :           break;
     387                 :            : 
     388                 :            :         case DW_OP_consts:
     389                 :            :         case DW_OP_breg0 ... DW_OP_breg31:
     390                 :            :         case DW_OP_fbreg:
     391                 :            :           /* XXX Check size.  */
     392         [ #  # ]:          0 :           get_sleb128 (newloc->number, data);
     393                 :            :           break;
     394                 :            : 
     395                 :            :         case DW_OP_bregx:
     396                 :            :           /* XXX Check size.  */
     397         [ #  # ]:          0 :           get_uleb128 (newloc->number, data);
     398         [ #  # ]:          0 :           get_sleb128 (newloc->number2, data);
     399                 :            :           break;
     400                 :            : 
     401                 :            :         case DW_OP_bit_piece:
     402                 :            :         case DW_OP_GNU_regval_type:
     403                 :            :           /* XXX Check size.  */
     404         [ #  # ]:          0 :           get_uleb128 (newloc->number, data);
     405         [ #  # ]:          0 :           get_uleb128 (newloc->number2, data);
     406                 :            :           break;
     407                 :            : 
     408                 :            :         case DW_OP_implicit_value:
     409                 :            :         case DW_OP_GNU_entry_value:
     410                 :            :           /* This cannot be used in a CFI expression.  */
     411         [ #  # ]:          0 :           if (unlikely (dbg == NULL))
     412                 :            :             goto invalid;
     413                 :            : 
     414                 :            :           /* XXX Check size.  */
     415         [ #  # ]:          0 :           get_uleb128 (newloc->number, data); /* Block length.  */
     416         [ #  # ]:          0 :           if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number))
     417                 :            :             goto invalid;
     418                 :          0 :           newloc->number2 = data - block->data; /* Relative block offset.  */
     419                 :          0 :           data += newloc->number;            /* Skip the block.  */
     420                 :          0 :           break;
     421                 :            : 
     422                 :            :         case DW_OP_GNU_implicit_pointer:
     423                 :            :           /* DW_FORM_ref_addr, depends on offset size of CU.  */
     424         [ #  # ]:          0 :           if (__libdw_read_offset_inc (dbg, sec_index, &data, ref_size,
     425                 :          0 :                                        &newloc->number, IDX_debug_info, 0))
     426                 :            :             return -1;
     427                 :            :           /* XXX Check size.  */
     428         [ #  # ]:          0 :           get_uleb128 (newloc->number2, data); /* Byte offset.  */
     429                 :            :           break;
     430                 :            : 
     431                 :            :         case DW_OP_GNU_deref_type:
     432         [ #  # ]:          0 :           if (unlikely (data >= end_data))
     433                 :            :             goto invalid;
     434                 :          0 :           newloc->number = *data++;
     435         [ #  # ]:          0 :           get_uleb128 (newloc->number2, data);
     436                 :            :           break;
     437                 :            : 
     438                 :            :         case DW_OP_GNU_const_type:
     439                 :            :           /* XXX Check size.  */
     440         [ #  # ]:          0 :           get_uleb128 (newloc->number, data);
     441         [ #  # ]:          0 :           if (unlikely (data >= end_data))
     442                 :            :             goto invalid;
     443                 :          0 :           newloc->number2 = *data++; /* Block length.  */
     444         [ #  # ]:          0 :           if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number2))
     445                 :            :             goto invalid;
     446                 :            :           /* The third operand is relative block offset:
     447                 :            :                 newloc->number3 = data - block->data;
     448                 :            :              We don't support this at this point.  */
     449                 :          0 :           data += newloc->number2;           /* Skip the block.  */
     450                 :       7332 :           break;
     451                 :            : 
     452                 :            :         default:
     453                 :            :           goto invalid;
     454                 :            :         }
     455                 :            :     }
     456                 :            : 
     457         [ -  + ]:       7080 :   if (unlikely (n == 0))
     458                 :            :     {
     459                 :            :       /* This is not allowed.
     460                 :            : 
     461                 :            :          XXX Is it?  */
     462                 :            :       goto invalid;
     463                 :            :     }
     464                 :            : 
     465         [ -  + ]:       7080 :   if (valuep)
     466                 :            :     {
     467                 :            :       struct loclist *newloc;
     468                 :          0 :       newloc = (struct loclist *) alloca (sizeof (struct loclist));
     469                 :          0 :       newloc->atom = DW_OP_stack_value;
     470                 :          0 :       newloc->number = 0;
     471                 :          0 :       newloc->number2 = 0;
     472                 :          0 :       newloc->offset = data - block->data;
     473                 :          0 :       newloc->next = loclist;
     474                 :          0 :       loclist = newloc;
     475                 :          0 :       ++n;
     476                 :            :     }
     477                 :            : 
     478                 :            :   /* Allocate the array.  */
     479                 :            :   Dwarf_Op *result;
     480         [ +  - ]:       7080 :   if (dbg != NULL)
     481         [ +  + ]:       7080 :     result = libdw_alloc (dbg, Dwarf_Op, sizeof (Dwarf_Op), n);
     482                 :            :   else
     483                 :            :     {
     484                 :          0 :       result = malloc (sizeof *result * n);
     485         [ #  # ]:          0 :       if (result == NULL)
     486                 :            :         {
     487                 :            :         nomem:
     488                 :          0 :           __libdw_seterrno (DWARF_E_NOMEM);
     489                 :            :           return -1;
     490                 :            :         }
     491                 :            :     }
     492                 :            : 
     493                 :            :   /* Store the result.  */
     494                 :       7080 :   *llbuf = result;
     495                 :       7080 :   *listlen = n;
     496                 :            : 
     497                 :            :   do
     498                 :            :     {
     499                 :            :       /* We populate the array from the back since the list is backwards.  */
     500                 :       7332 :       --n;
     501                 :       7332 :       result[n].atom = loclist->atom;
     502                 :       7332 :       result[n].number = loclist->number;
     503                 :       7332 :       result[n].number2 = loclist->number2;
     504                 :       7332 :       result[n].offset = loclist->offset;
     505                 :            : 
     506         [ -  + ]:       7332 :       if (result[n].atom == DW_OP_implicit_value)
     507                 :          0 :         store_implicit_value (dbg, cache, &result[n], block->data);
     508                 :            : 
     509                 :       7332 :       loclist = loclist->next;
     510                 :            :     }
     511         [ +  + ]:       7332 :   while (n > 0);
     512                 :            : 
     513                 :            :   /* Insert a record in the search tree so that we can find it again later.  */
     514                 :            :   struct loc_s *newp;
     515         [ +  - ]:       7080 :   if (dbg != NULL)
     516         [ -  + ]:       7080 :     newp = libdw_alloc (dbg, struct loc_s, sizeof (struct loc_s), 1);
     517                 :            :   else
     518                 :            :     {
     519                 :          0 :       newp = malloc (sizeof *newp);
     520         [ #  # ]:          0 :       if (newp == NULL)
     521                 :            :         {
     522                 :          0 :           free (result);
     523                 :          0 :           goto nomem;
     524                 :            :         }
     525                 :            :     }
     526                 :            : 
     527                 :       7080 :   newp->addr = block->data;
     528                 :       7080 :   newp->loc = result;
     529                 :       7080 :   newp->nloc = *listlen;
     530                 :       7080 :   (void) tsearch (newp, cache, loc_compare);
     531                 :            : 
     532                 :            :   /* We did it.  */
     533                 :            :   return 0;
     534                 :            : }
     535                 :            : 
     536                 :            : static int
     537                 :       7080 : getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
     538                 :            :              Dwarf_Op **llbuf, size_t *listlen, int sec_index)
     539                 :            : {
     540         [ -  + ]:       7080 :   return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order,
     541                 :      14160 :                                     cu->address_size, (cu->version == 2
     542                 :          0 :                                                        ? cu->address_size
     543                 :       7080 :                                                        : cu->offset_size),
     544                 :            :                                     &cu->locs, block,
     545                 :            :                                     false, false,
     546                 :            :                                     llbuf, listlen, sec_index);
     547                 :            : }
     548                 :            : 
     549                 :            : int
     550                 :       7080 : dwarf_getlocation (attr, llbuf, listlen)
     551                 :            :      Dwarf_Attribute *attr;
     552                 :            :      Dwarf_Op **llbuf;
     553                 :            :      size_t *listlen;
     554                 :            : {
     555         [ +  - ]:       7080 :   if (! attr_ok (attr))
     556                 :            :     return -1;
     557                 :            : 
     558                 :       7080 :   int result = check_constant_offset (attr, llbuf, listlen);
     559         [ +  - ]:       7080 :   if (result != 1)
     560                 :            :     return result;
     561                 :            : 
     562                 :            :   /* If it has a block form, it's a single location expression.  */
     563                 :            :   Dwarf_Block block;
     564         [ +  - ]:       7080 :   if (INTUSE(dwarf_formblock) (attr, &block) != 0)
     565                 :            :     return -1;
     566                 :            : 
     567                 :       7080 :   return getlocation (attr->cu, &block, llbuf, listlen, cu_sec_idx (attr->cu));
     568                 :            : }
     569                 :            : 
     570                 :            : int
     571                 :          0 : dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs)
     572                 :            :      Dwarf_Attribute *attr;
     573                 :            :      Dwarf_Addr address;
     574                 :            :      Dwarf_Op **llbufs;
     575                 :            :      size_t *listlens;
     576                 :            :      size_t maxlocs;
     577                 :            : {
     578         [ #  # ]:          0 :   if (! attr_ok (attr))
     579                 :            :     return -1;
     580                 :            : 
     581         [ #  # ]:          0 :   if (llbufs == NULL)
     582                 :          0 :     maxlocs = SIZE_MAX;
     583                 :            : 
     584                 :            :   /* If it has a block form, it's a single location expression.  */
     585                 :            :   Dwarf_Block block;
     586         [ #  # ]:          0 :   if (INTUSE(dwarf_formblock) (attr, &block) == 0)
     587                 :            :     {
     588         [ #  # ]:          0 :       if (maxlocs == 0)
     589                 :            :         return 0;
     590   [ #  #  #  # ]:          0 :       if (llbufs != NULL &&
     591                 :          0 :           getlocation (attr->cu, &block, &llbufs[0], &listlens[0],
     592                 :          0 :                        cu_sec_idx (attr->cu)) != 0)
     593                 :            :         return -1;
     594                 :          0 :       return listlens[0] == 0 ? 0 : 1;
     595                 :            :     }
     596                 :            : 
     597                 :          0 :   int error = INTUSE(dwarf_errno) ();
     598         [ #  # ]:          0 :   if (unlikely (error != DWARF_E_NO_BLOCK))
     599                 :            :     {
     600                 :          0 :       __libdw_seterrno (error);
     601                 :            :       return -1;
     602                 :            :     }
     603                 :            : 
     604                 :          0 :   int result = check_constant_offset (attr, &llbufs[0], &listlens[0]);
     605         [ #  # ]:          0 :   if (result != 1)
     606         [ #  # ]:          0 :     return result ?: 1;
     607                 :            : 
     608                 :            :   unsigned char *endp;
     609                 :          0 :   unsigned char *readp = __libdw_formptr (attr, IDX_debug_loc,
     610                 :            :                                           DWARF_E_NO_LOCLIST, &endp, NULL);
     611         [ #  # ]:          0 :   if (readp == NULL)
     612                 :            :     return -1;
     613                 :            : 
     614                 :          0 :   Dwarf_Addr base = (Dwarf_Addr) -1;
     615                 :          0 :   size_t got = 0;
     616         [ #  # ]:          0 :   while (got < maxlocs)
     617                 :            :     {
     618         [ #  # ]:          0 :       if (endp - readp < attr->cu->address_size * 2)
     619                 :            :         {
     620                 :            :         invalid:
     621                 :          0 :           __libdw_seterrno (DWARF_E_INVALID_DWARF);
     622                 :            :           return -1;
     623                 :            :         }
     624                 :            : 
     625                 :            :       Dwarf_Addr begin;
     626                 :            :       Dwarf_Addr end;
     627                 :            : 
     628                 :          0 :       int status
     629                 :          0 :         = __libdw_read_begin_end_pair_inc (attr->cu->dbg, IDX_debug_loc,
     630                 :            :                                            &readp, attr->cu->address_size,
     631                 :            :                                            &begin, &end, &base);
     632         [ #  # ]:          0 :       if (status == 2) /* End of list entry.  */
     633                 :            :         break;
     634         [ #  # ]:          0 :       else if (status == 1) /* Base address selected.  */
     635                 :          0 :         continue;
     636         [ #  # ]:          0 :       else if (status < 0)
     637                 :            :         return status;
     638                 :            : 
     639         [ #  # ]:          0 :       if (endp - readp < 2)
     640                 :            :         goto invalid;
     641                 :            : 
     642                 :            :       /* We have a location expression.  */
     643 [ #  # ][ #  # ]:          0 :       block.length = read_2ubyte_unaligned_inc (attr->cu->dbg, readp);
     644                 :          0 :       block.data = readp;
     645         [ #  # ]:          0 :       if (endp - readp < (ptrdiff_t) block.length)
     646                 :            :         goto invalid;
     647                 :          0 :       readp += block.length;
     648                 :            : 
     649         [ #  # ]:          0 :       if (base == (Dwarf_Addr) -1)
     650                 :            :         {
     651                 :            :           /* Fetch the CU's base address.  */
     652         [ #  # ]:          0 :           Dwarf_Die cudie = CUDIE (attr->cu);
     653                 :            : 
     654                 :            :           /* Find the base address of the compilation unit.  It will
     655                 :            :              normally be specified by DW_AT_low_pc.  In DWARF-3 draft 4,
     656                 :            :              the base address could be overridden by DW_AT_entry_pc.  It's
     657                 :            :              been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc
     658                 :            :              for compilation units with discontinuous ranges.  */
     659                 :            :           Dwarf_Attribute attr_mem;
     660         [ #  # ]:          0 :           if (unlikely (INTUSE(dwarf_lowpc) (&cudie, &base) != 0)
     661         [ #  # ]:          0 :               && INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (&cudie,
     662                 :            :                                                              DW_AT_entry_pc,
     663                 :            :                                                              &attr_mem),
     664                 :            :                                          &base) != 0)
     665                 :            :             {
     666         [ #  # ]:          0 :               if (INTUSE(dwarf_errno) () != 0)
     667                 :            :                 return -1;
     668                 :            : 
     669                 :            :               /* The compiler provided no base address when it should
     670                 :            :                  have.  Buggy GCC does this when it used absolute
     671                 :            :                  addresses in the location list and no DW_AT_ranges.  */
     672                 :          0 :               base = 0;
     673                 :            :             }
     674                 :            :         }
     675                 :            : 
     676 [ #  # ][ #  # ]:          0 :       if (address >= base + begin && address < base + end)
     677                 :            :         {
     678                 :            :           /* This one matches the address.  */
     679         [ #  # ]:          0 :           if (llbufs != NULL
     680         [ #  # ]:          0 :               && unlikely (getlocation (attr->cu, &block,
     681                 :            :                                         &llbufs[got], &listlens[got],
     682                 :            :                                         IDX_debug_loc) != 0))
     683                 :            :             return -1;
     684                 :          0 :           ++got;
     685                 :            :         }
     686                 :            :     }
     687                 :            : 
     688                 :          0 :   return got;
     689                 :       7080 : }

Generated by: LCOV version 1.9