Home | History | Annotate | Download | only in libdw
      1 /* Return location expression list.
      2    Copyright (C) 2000-2010, 2013-2015 Red Hat, Inc.
      3    This file is part of elfutils.
      4    Written by Ulrich Drepper <drepper (at) 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 attr_ok (Dwarf_Attribute *attr)
     44 {
     45   if (attr == NULL)
     46     return false;
     47 
     48   /* Must be one of the attributes listed below.  */
     49   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     case DW_AT_segment:
     60     case DW_AT_GNU_call_site_value:
     61     case DW_AT_GNU_call_site_data_value:
     62     case DW_AT_GNU_call_site_target:
     63     case DW_AT_GNU_call_site_target_clobbered:
     64       break;
     65 
     66     default:
     67       __libdw_seterrno (DWARF_E_NO_LOCLIST);
     68       return false;
     69     }
     70 
     71   return true;
     72 }
     73 
     74 
     75 struct loclist
     76 {
     77   uint8_t atom;
     78   Dwarf_Word number;
     79   Dwarf_Word number2;
     80   Dwarf_Word offset;
     81   struct loclist *next;
     82 };
     83 
     84 
     85 static int
     86 loc_compare (const void *p1, const void *p2)
     87 {
     88   const struct loc_s *l1 = (const struct loc_s *) p1;
     89   const struct loc_s *l2 = (const struct loc_s *) p2;
     90 
     91   if ((uintptr_t) l1->addr < (uintptr_t) l2->addr)
     92     return -1;
     93   if ((uintptr_t) l1->addr > (uintptr_t) l2->addr)
     94     return 1;
     95 
     96   return 0;
     97 }
     98 
     99 /* For each DW_OP_implicit_value, we store a special entry in the cache.
    100    This points us directly to the block data for later fetching.  */
    101 static void
    102 store_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op)
    103 {
    104   struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s,
    105 					   sizeof (struct loc_block_s), 1);
    106   const unsigned char *data = (const unsigned char *) (uintptr_t) op->number2;
    107   // Ignored, equal to op->number.  And data length already checked.
    108   (void) __libdw_get_uleb128 (&data, data + len_leb128 (Dwarf_Word));
    109   block->addr = op;
    110   block->data = (unsigned char *) data;
    111   block->length = op->number;
    112   (void) tsearch (block, cache, loc_compare);
    113 }
    114 
    115 int
    116 dwarf_getlocation_implicit_value (Dwarf_Attribute *attr, const Dwarf_Op *op,
    117 				  Dwarf_Block *return_block)
    118 {
    119   if (attr == NULL)
    120     return -1;
    121 
    122   struct loc_block_s fake = { .addr = (void *) op };
    123   struct loc_block_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
    124   if (unlikely (found == NULL))
    125     {
    126       __libdw_seterrno (DWARF_E_NO_BLOCK);
    127       return -1;
    128     }
    129 
    130   return_block->length = (*found)->length;
    131   return_block->data = (*found)->data;
    132   return 0;
    133 }
    134 
    135 /* DW_AT_data_member_location can be a constant as well as a loclistptr.
    136    Only data[48] indicate a loclistptr.  */
    137 static int
    138 check_constant_offset (Dwarf_Attribute *attr,
    139 		       Dwarf_Op **llbuf, size_t *listlen)
    140 {
    141   if (attr->code != DW_AT_data_member_location)
    142     return 1;
    143 
    144   switch (attr->form)
    145     {
    146       /* Punt for any non-constant form.  */
    147     default:
    148       return 1;
    149 
    150     case DW_FORM_data1:
    151     case DW_FORM_data2:
    152     case DW_FORM_data4:
    153     case DW_FORM_data8:
    154     case DW_FORM_sdata:
    155     case DW_FORM_udata:
    156       break;
    157     }
    158 
    159   /* Check whether we already cached this location.  */
    160   struct loc_s fake = { .addr = attr->valp };
    161   struct loc_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
    162 
    163   if (found == NULL)
    164     {
    165       Dwarf_Word offset;
    166       if (INTUSE(dwarf_formudata) (attr, &offset) != 0)
    167 	return -1;
    168 
    169       Dwarf_Op *result = libdw_alloc (attr->cu->dbg,
    170 				      Dwarf_Op, sizeof (Dwarf_Op), 1);
    171 
    172       result->atom = DW_OP_plus_uconst;
    173       result->number = offset;
    174       result->number2 = 0;
    175       result->offset = 0;
    176 
    177       /* Insert a record in the search tree so we can find it again later.  */
    178       struct loc_s *newp = libdw_alloc (attr->cu->dbg,
    179 					struct loc_s, sizeof (struct loc_s),
    180 					1);
    181       newp->addr = attr->valp;
    182       newp->loc = result;
    183       newp->nloc = 1;
    184 
    185       found = tsearch (newp, &attr->cu->locs, loc_compare);
    186     }
    187 
    188   assert ((*found)->nloc == 1);
    189 
    190   if (llbuf != NULL)
    191     {
    192       *llbuf = (*found)->loc;
    193       *listlen = 1;
    194     }
    195 
    196   return 0;
    197 }
    198 
    199 int
    200 internal_function
    201 __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
    202 			   unsigned int address_size, unsigned int ref_size,
    203 			   void **cache, const Dwarf_Block *block,
    204 			   bool cfap, bool valuep,
    205 			   Dwarf_Op **llbuf, size_t *listlen, int sec_index)
    206 {
    207   /* Empty location expressions don't have any ops to intern.  */
    208   if (block->length == 0)
    209     {
    210       *listlen = 0;
    211       return 0;
    212     }
    213 
    214   /* Check whether we already looked at this list.  */
    215   struct loc_s fake = { .addr = block->data };
    216   struct loc_s **found = tfind (&fake, cache, loc_compare);
    217   if (found != NULL)
    218     {
    219       /* We already saw it.  */
    220       *llbuf = (*found)->loc;
    221       *listlen = (*found)->nloc;
    222 
    223       if (valuep)
    224 	{
    225 	  assert (*listlen > 1);
    226 	  assert ((*llbuf)[*listlen - 1].atom == DW_OP_stack_value);
    227 	}
    228 
    229       return 0;
    230     }
    231 
    232   const unsigned char *data = block->data;
    233   const unsigned char *const end_data = data + block->length;
    234 
    235   const struct { bool other_byte_order; } bo = { other_byte_order };
    236 
    237   struct loclist *loclist = NULL;
    238   unsigned int n = 0;
    239 
    240   /* Stack allocate at most this many locs.  */
    241 #define MAX_STACK_LOCS 256
    242   struct loclist stack_locs[MAX_STACK_LOCS];
    243 #define NEW_LOC() ({ struct loclist *ll;			\
    244 		     ll = (likely (n < MAX_STACK_LOCS)		\
    245 			   ? &stack_locs[n]			\
    246 			   : malloc (sizeof (struct loclist)));	\
    247 		     if (unlikely (ll == NULL))			\
    248 		       goto nomem;				\
    249 		     n++;					\
    250 		     ll->next = loclist;			\
    251 		     loclist = ll;				\
    252 		     ll; })
    253 
    254   if (cfap)
    255     {
    256       /* Synthesize the operation to push the CFA before the expression.  */
    257       struct loclist *newloc = NEW_LOC ();
    258       newloc->atom = DW_OP_call_frame_cfa;
    259       newloc->number = 0;
    260       newloc->number2 = 0;
    261       newloc->offset = -1;
    262     }
    263 
    264   /* Decode the opcodes.  It is possible in some situations to have a
    265      block of size zero.  */
    266   while (data < end_data)
    267     {
    268       struct loclist *newloc;
    269       newloc = NEW_LOC ();
    270       newloc->number = 0;
    271       newloc->number2 = 0;
    272       newloc->offset = data - block->data;
    273 
    274       switch ((newloc->atom = *data++))
    275 	{
    276 	case DW_OP_addr:
    277 	  /* Address, depends on address size of CU.  */
    278 	  if (dbg == NULL)
    279 	    {
    280 	      // XXX relocation?
    281 	      if (address_size == 4)
    282 		{
    283 		  if (unlikely (data + 4 > end_data))
    284 		    goto invalid;
    285 		  else
    286 		    newloc->number = read_4ubyte_unaligned_inc (&bo, data);
    287 		}
    288 	      else
    289 		{
    290 		  if (unlikely (data + 8 > end_data))
    291 		    goto invalid;
    292 		  else
    293 		    newloc->number = read_8ubyte_unaligned_inc (&bo, data);
    294 		}
    295 	    }
    296 	  else if (__libdw_read_address_inc (dbg, sec_index, &data,
    297 					     address_size, &newloc->number))
    298 	    goto invalid;
    299 	  break;
    300 
    301 	case DW_OP_call_ref:
    302 	  /* DW_FORM_ref_addr, depends on offset size of CU.  */
    303 	  if (dbg == NULL || __libdw_read_offset_inc (dbg, sec_index, &data,
    304 						      ref_size,
    305 						      &newloc->number,
    306 						      IDX_debug_info, 0))
    307 	    goto invalid;
    308 	  break;
    309 
    310 	case DW_OP_deref:
    311 	case DW_OP_dup:
    312 	case DW_OP_drop:
    313 	case DW_OP_over:
    314 	case DW_OP_swap:
    315 	case DW_OP_rot:
    316 	case DW_OP_xderef:
    317 	case DW_OP_abs:
    318 	case DW_OP_and:
    319 	case DW_OP_div:
    320 	case DW_OP_minus:
    321 	case DW_OP_mod:
    322 	case DW_OP_mul:
    323 	case DW_OP_neg:
    324 	case DW_OP_not:
    325 	case DW_OP_or:
    326 	case DW_OP_plus:
    327 	case DW_OP_shl:
    328 	case DW_OP_shr:
    329 	case DW_OP_shra:
    330 	case DW_OP_xor:
    331 	case DW_OP_eq:
    332 	case DW_OP_ge:
    333 	case DW_OP_gt:
    334 	case DW_OP_le:
    335 	case DW_OP_lt:
    336 	case DW_OP_ne:
    337 	case DW_OP_lit0 ... DW_OP_lit31:
    338 	case DW_OP_reg0 ... DW_OP_reg31:
    339 	case DW_OP_nop:
    340 	case DW_OP_push_object_address:
    341 	case DW_OP_call_frame_cfa:
    342 	case DW_OP_form_tls_address:
    343 	case DW_OP_GNU_push_tls_address:
    344 	case DW_OP_stack_value:
    345 	  /* No operand.  */
    346 	  break;
    347 
    348 	case DW_OP_const1u:
    349 	case DW_OP_pick:
    350 	case DW_OP_deref_size:
    351 	case DW_OP_xderef_size:
    352 	  if (unlikely (data >= end_data))
    353 	    {
    354 	    invalid:
    355 	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
    356 	    returnmem:
    357 	      /* Free any dynamicly allocated loclists, if any.  */
    358 	      while (n > MAX_STACK_LOCS)
    359 		{
    360 		  struct loclist *loc = loclist;
    361 		  loclist = loc->next;
    362 		  free (loc);
    363 		  n--;
    364 		}
    365 	      return -1;
    366 	    }
    367 
    368 	  newloc->number = *data++;
    369 	  break;
    370 
    371 	case DW_OP_const1s:
    372 	  if (unlikely (data >= end_data))
    373 	    goto invalid;
    374 
    375 	  newloc->number = *((int8_t *) data);
    376 	  ++data;
    377 	  break;
    378 
    379 	case DW_OP_const2u:
    380 	  if (unlikely (data + 2 > end_data))
    381 	    goto invalid;
    382 
    383 	  newloc->number = read_2ubyte_unaligned_inc (&bo, data);
    384 	  break;
    385 
    386 	case DW_OP_const2s:
    387 	case DW_OP_skip:
    388 	case DW_OP_bra:
    389 	case DW_OP_call2:
    390 	  if (unlikely (data + 2 > end_data))
    391 	    goto invalid;
    392 
    393 	  newloc->number = read_2sbyte_unaligned_inc (&bo, data);
    394 	  break;
    395 
    396 	case DW_OP_const4u:
    397 	  if (unlikely (data + 4 > end_data))
    398 	    goto invalid;
    399 
    400 	  newloc->number = read_4ubyte_unaligned_inc (&bo, data);
    401 	  break;
    402 
    403 	case DW_OP_const4s:
    404 	case DW_OP_call4:
    405 	case DW_OP_GNU_parameter_ref:
    406 	  if (unlikely (data + 4 > end_data))
    407 	    goto invalid;
    408 
    409 	  newloc->number = read_4sbyte_unaligned_inc (&bo, data);
    410 	  break;
    411 
    412 	case DW_OP_const8u:
    413 	  if (unlikely (data + 8 > end_data))
    414 	    goto invalid;
    415 
    416 	  newloc->number = read_8ubyte_unaligned_inc (&bo, data);
    417 	  break;
    418 
    419 	case DW_OP_const8s:
    420 	  if (unlikely (data + 8 > end_data))
    421 	    goto invalid;
    422 
    423 	  newloc->number = read_8sbyte_unaligned_inc (&bo, data);
    424 	  break;
    425 
    426 	case DW_OP_constu:
    427 	case DW_OP_plus_uconst:
    428 	case DW_OP_regx:
    429 	case DW_OP_piece:
    430 	case DW_OP_GNU_convert:
    431 	case DW_OP_GNU_reinterpret:
    432 	  get_uleb128 (newloc->number, data, end_data);
    433 	  break;
    434 
    435 	case DW_OP_consts:
    436 	case DW_OP_breg0 ... DW_OP_breg31:
    437 	case DW_OP_fbreg:
    438 	  get_sleb128 (newloc->number, data, end_data);
    439 	  break;
    440 
    441 	case DW_OP_bregx:
    442 	  get_uleb128 (newloc->number, data, end_data);
    443 	  if (unlikely (data >= end_data))
    444 	    goto invalid;
    445 	  get_sleb128 (newloc->number2, data, end_data);
    446 	  break;
    447 
    448 	case DW_OP_bit_piece:
    449 	case DW_OP_GNU_regval_type:
    450 	  get_uleb128 (newloc->number, data, end_data);
    451 	  if (unlikely (data >= end_data))
    452 	    goto invalid;
    453 	  get_uleb128 (newloc->number2, data, end_data);
    454 	  break;
    455 
    456 	case DW_OP_implicit_value:
    457 	case DW_OP_GNU_entry_value:
    458 	  /* This cannot be used in a CFI expression.  */
    459 	  if (unlikely (dbg == NULL))
    460 	    goto invalid;
    461 
    462 	  /* start of block inc. len.  */
    463 	  newloc->number2 = (Dwarf_Word) (uintptr_t) data;
    464 	  get_uleb128 (newloc->number, data, end_data); /* Block length.  */
    465 	  if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number))
    466 	    goto invalid;
    467 	  data += newloc->number;		/* Skip the block.  */
    468 	  break;
    469 
    470 	case DW_OP_GNU_implicit_pointer:
    471 	  /* DW_FORM_ref_addr, depends on offset size of CU.  */
    472 	  if (dbg == NULL || __libdw_read_offset_inc (dbg, sec_index, &data,
    473 						      ref_size,
    474 						      &newloc->number,
    475 						      IDX_debug_info, 0))
    476 	    goto invalid;
    477 	  if (unlikely (data >= end_data))
    478 	    goto invalid;
    479 	  get_uleb128 (newloc->number2, data, end_data); /* Byte offset.  */
    480 	  break;
    481 
    482 	case DW_OP_GNU_deref_type:
    483 	  if (unlikely (data + 1 >= end_data))
    484 	    goto invalid;
    485 	  newloc->number = *data++;
    486 	  get_uleb128 (newloc->number2, data, end_data);
    487 	  break;
    488 
    489 	case DW_OP_GNU_const_type:
    490 	  {
    491 	    size_t size;
    492 	    get_uleb128 (newloc->number, data, end_data);
    493 	    if (unlikely (data >= end_data))
    494 	      goto invalid;
    495 
    496 	    /* start of block inc. len.  */
    497 	    newloc->number2 = (Dwarf_Word) (uintptr_t) data;
    498 	    size = *data++;
    499 	    if (unlikely ((Dwarf_Word) (end_data - data) < size))
    500 	      goto invalid;
    501 	    data += size;		/* Skip the block.  */
    502 	  }
    503 	  break;
    504 
    505 	default:
    506 	  goto invalid;
    507 	}
    508     }
    509 
    510   if (unlikely (n == 0))
    511     {
    512       /* This is not allowed.
    513 	 It would mean an empty location expression, which we handled
    514 	 already as a special case above.  */
    515       goto invalid;
    516     }
    517 
    518   if (valuep)
    519     {
    520       struct loclist *newloc = NEW_LOC ();
    521       newloc->atom = DW_OP_stack_value;
    522       newloc->number = 0;
    523       newloc->number2 = 0;
    524       newloc->offset = data - block->data;
    525     }
    526 
    527   /* Allocate the array.  */
    528   Dwarf_Op *result;
    529   if (dbg != NULL)
    530     result = libdw_alloc (dbg, Dwarf_Op, sizeof (Dwarf_Op), n);
    531   else
    532     {
    533       result = malloc (sizeof *result * n);
    534       if (result == NULL)
    535 	{
    536 	nomem:
    537 	  __libdw_seterrno (DWARF_E_NOMEM);
    538 	  goto returnmem;
    539 	}
    540     }
    541 
    542   /* Store the result.  */
    543   *llbuf = result;
    544   *listlen = n;
    545 
    546   do
    547     {
    548       /* We populate the array from the back since the list is backwards.  */
    549       --n;
    550       result[n].atom = loclist->atom;
    551       result[n].number = loclist->number;
    552       result[n].number2 = loclist->number2;
    553       result[n].offset = loclist->offset;
    554 
    555       if (result[n].atom == DW_OP_implicit_value)
    556 	store_implicit_value (dbg, cache, &result[n]);
    557 
    558       struct loclist *loc = loclist;
    559       loclist = loclist->next;
    560       if (unlikely (n + 1 > MAX_STACK_LOCS))
    561 	free (loc);
    562     }
    563   while (n > 0);
    564 
    565   /* Insert a record in the search tree so that we can find it again later.  */
    566   struct loc_s *newp;
    567   if (dbg != NULL)
    568     newp = libdw_alloc (dbg, struct loc_s, sizeof (struct loc_s), 1);
    569   else
    570     {
    571       newp = malloc (sizeof *newp);
    572       if (newp == NULL)
    573 	{
    574 	  free (result);
    575 	  goto nomem;
    576 	}
    577     }
    578 
    579   newp->addr = block->data;
    580   newp->loc = result;
    581   newp->nloc = *listlen;
    582   (void) tsearch (newp, cache, loc_compare);
    583 
    584   /* We did it.  */
    585   return 0;
    586 }
    587 
    588 static int
    589 getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
    590 	     Dwarf_Op **llbuf, size_t *listlen, int sec_index)
    591 {
    592   /* Empty location expressions don't have any ops to intern.
    593      Note that synthetic empty_cu doesn't have an associated DWARF dbg.  */
    594   if (block->length == 0)
    595     {
    596       *listlen = 0;
    597       return 0;
    598     }
    599 
    600   return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order,
    601 				    cu->address_size, (cu->version == 2
    602 						       ? cu->address_size
    603 						       : cu->offset_size),
    604 				    &cu->locs, block,
    605 				    false, false,
    606 				    llbuf, listlen, sec_index);
    607 }
    608 
    609 int
    610 dwarf_getlocation (Dwarf_Attribute *attr, Dwarf_Op **llbuf, size_t *listlen)
    611 {
    612   if (! attr_ok (attr))
    613     return -1;
    614 
    615   int result = check_constant_offset (attr, llbuf, listlen);
    616   if (result != 1)
    617     return result;
    618 
    619   /* If it has a block form, it's a single location expression.  */
    620   Dwarf_Block block;
    621   if (INTUSE(dwarf_formblock) (attr, &block) != 0)
    622     return -1;
    623 
    624   return getlocation (attr->cu, &block, llbuf, listlen, cu_sec_idx (attr->cu));
    625 }
    626 
    627 static int
    628 attr_base_address (Dwarf_Attribute *attr, Dwarf_Addr *basep)
    629 {
    630   /* Fetch the CU's base address.  */
    631   Dwarf_Die cudie = CUDIE (attr->cu);
    632 
    633   /* Find the base address of the compilation unit.  It will
    634      normally be specified by DW_AT_low_pc.  In DWARF-3 draft 4,
    635      the base address could be overridden by DW_AT_entry_pc.  It's
    636      been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc
    637      for compilation units with discontinuous ranges.  */
    638   Dwarf_Attribute attr_mem;
    639   if (unlikely (INTUSE(dwarf_lowpc) (&cudie, basep) != 0)
    640       && INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (&cudie,
    641 						     DW_AT_entry_pc,
    642 						     &attr_mem),
    643 				 basep) != 0)
    644     {
    645       if (INTUSE(dwarf_errno) () != 0)
    646 	return -1;
    647 
    648       /* The compiler provided no base address when it should
    649 	 have.  Buggy GCC does this when it used absolute
    650 	 addresses in the location list and no DW_AT_ranges.  */
    651       *basep = 0;
    652     }
    653   return 0;
    654 }
    655 
    656 static int
    657 initial_offset_base (Dwarf_Attribute *attr, ptrdiff_t *offset,
    658 		     Dwarf_Addr *basep)
    659 {
    660   if (attr_base_address (attr, basep) != 0)
    661     return -1;
    662 
    663   Dwarf_Word start_offset;
    664   if (__libdw_formptr (attr, IDX_debug_loc,
    665 		       DWARF_E_NO_LOCLIST,
    666 		       NULL, &start_offset) == NULL)
    667     return -1;
    668 
    669   *offset = start_offset;
    670   return 0;
    671 }
    672 
    673 static ptrdiff_t
    674 getlocations_addr (Dwarf_Attribute *attr, ptrdiff_t offset,
    675 		   Dwarf_Addr *basep, Dwarf_Addr *startp, Dwarf_Addr *endp,
    676 		   Dwarf_Addr address, const Elf_Data *locs, Dwarf_Op **expr,
    677 		   size_t *exprlen)
    678 {
    679   unsigned char *readp = locs->d_buf + offset;
    680   unsigned char *readendp = locs->d_buf + locs->d_size;
    681 
    682  next:
    683   if (readendp - readp < attr->cu->address_size * 2)
    684     {
    685     invalid:
    686       __libdw_seterrno (DWARF_E_INVALID_DWARF);
    687       return -1;
    688     }
    689 
    690   Dwarf_Addr begin;
    691   Dwarf_Addr end;
    692 
    693   switch (__libdw_read_begin_end_pair_inc (attr->cu->dbg, IDX_debug_loc,
    694 					   &readp, attr->cu->address_size,
    695 					   &begin, &end, basep))
    696     {
    697     case 0: /* got location range. */
    698       break;
    699     case 1: /* base address setup. */
    700       goto next;
    701     case 2: /* end of loclist */
    702       return 0;
    703     default: /* error */
    704       return -1;
    705     }
    706 
    707   if (readendp - readp < 2)
    708     goto invalid;
    709 
    710   /* We have a location expression.  */
    711   Dwarf_Block block;
    712   block.length = read_2ubyte_unaligned_inc (attr->cu->dbg, readp);
    713   block.data = readp;
    714   if (readendp - readp < (ptrdiff_t) block.length)
    715     goto invalid;
    716   readp += block.length;
    717 
    718   *startp = *basep + begin;
    719   *endp = *basep + end;
    720 
    721   /* If address is minus one we want them all, otherwise only matching.  */
    722   if (address != (Dwarf_Word) -1 && (address < *startp || address >= *endp))
    723     goto next;
    724 
    725   if (getlocation (attr->cu, &block, expr, exprlen, IDX_debug_loc) != 0)
    726     return -1;
    727 
    728   return readp - (unsigned char *) locs->d_buf;
    729 }
    730 
    731 int
    732 dwarf_getlocation_addr (Dwarf_Attribute *attr, Dwarf_Addr address,
    733 			Dwarf_Op **llbufs, size_t *listlens, size_t maxlocs)
    734 {
    735   if (! attr_ok (attr))
    736     return -1;
    737 
    738   if (llbufs == NULL)
    739     maxlocs = SIZE_MAX;
    740 
    741   /* If it has a block form, it's a single location expression.  */
    742   Dwarf_Block block;
    743   if (INTUSE(dwarf_formblock) (attr, &block) == 0)
    744     {
    745       if (maxlocs == 0)
    746 	return 0;
    747       if (llbufs != NULL &&
    748 	  getlocation (attr->cu, &block, &llbufs[0], &listlens[0],
    749 		       cu_sec_idx (attr->cu)) != 0)
    750 	return -1;
    751       return listlens[0] == 0 ? 0 : 1;
    752     }
    753 
    754   int error = INTUSE(dwarf_errno) ();
    755   if (unlikely (error != DWARF_E_NO_BLOCK))
    756     {
    757       __libdw_seterrno (error);
    758       return -1;
    759     }
    760 
    761   int result = check_constant_offset (attr, &llbufs[0], &listlens[0]);
    762   if (result != 1)
    763     return result ?: 1;
    764 
    765   Dwarf_Addr base, start, end;
    766   Dwarf_Op *expr;
    767   size_t expr_len;
    768   ptrdiff_t off = 0;
    769   size_t got = 0;
    770 
    771   /* This is a true loclistptr, fetch the initial base address and offset.  */
    772   if (initial_offset_base (attr, &off, &base) != 0)
    773     return -1;
    774 
    775   const Elf_Data *d = attr->cu->dbg->sectiondata[IDX_debug_loc];
    776   if (d == NULL)
    777     {
    778       __libdw_seterrno (DWARF_E_NO_LOCLIST);
    779       return -1;
    780     }
    781 
    782   while (got < maxlocs
    783          && (off = getlocations_addr (attr, off, &base, &start, &end,
    784 				   address, d, &expr, &expr_len)) > 0)
    785     {
    786       /* This one matches the address.  */
    787       if (llbufs != NULL)
    788 	{
    789 	  llbufs[got] = expr;
    790 	  listlens[got] = expr_len;
    791 	}
    792       ++got;
    793     }
    794 
    795   /* We might stop early, so off can be zero or positive on success.  */
    796   if (off < 0)
    797     return -1;
    798 
    799   return got;
    800 }
    801 
    802 ptrdiff_t
    803 dwarf_getlocations (Dwarf_Attribute *attr, ptrdiff_t offset, Dwarf_Addr *basep,
    804 		    Dwarf_Addr *startp, Dwarf_Addr *endp, Dwarf_Op **expr,
    805 		    size_t *exprlen)
    806 {
    807   if (! attr_ok (attr))
    808     return -1;
    809 
    810   /* 1 is an invalid offset, meaning no more locations. */
    811   if (offset == 1)
    812     return 0;
    813 
    814   if (offset == 0)
    815     {
    816       /* If it has a block form, it's a single location expression.  */
    817       Dwarf_Block block;
    818       if (INTUSE(dwarf_formblock) (attr, &block) == 0)
    819 	{
    820 	  if (getlocation (attr->cu, &block, expr, exprlen,
    821 			   cu_sec_idx (attr->cu)) != 0)
    822 	    return -1;
    823 
    824 	  /* This is the one and only location covering everything. */
    825 	  *startp = 0;
    826 	  *endp = -1;
    827 	  return 1;
    828 	}
    829 
    830       int error = INTUSE(dwarf_errno) ();
    831       if (unlikely (error != DWARF_E_NO_BLOCK))
    832 	{
    833 	  __libdw_seterrno (error);
    834 	  return -1;
    835 	}
    836 
    837       int result = check_constant_offset (attr, expr, exprlen);
    838       if (result != 1)
    839 	{
    840 	  if (result == 0)
    841 	    {
    842 	      /* This is the one and only location covering everything. */
    843 	      *startp = 0;
    844 	      *endp = -1;
    845 	      return 1;
    846 	    }
    847 	  return result;
    848 	}
    849 
    850       /* We must be looking at a true loclistptr, fetch the initial
    851 	 base address and offset.  */
    852       if (initial_offset_base (attr, &offset, basep) != 0)
    853 	return -1;
    854     }
    855 
    856   const Elf_Data *d = attr->cu->dbg->sectiondata[IDX_debug_loc];
    857   if (d == NULL)
    858     {
    859       __libdw_seterrno (DWARF_E_NO_LOCLIST);
    860       return -1;
    861     }
    862 
    863   return getlocations_addr (attr, offset, basep, startp, endp,
    864 			    (Dwarf_Word) -1, d, expr, exprlen);
    865 }
    866