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@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
42static bool
43attr_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
75struct 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
85static int
86loc_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.  */
101static void
102store_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
115int
116dwarf_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.  */
137static int
138check_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
199int
200internal_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
588static int
589getlocation (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
609int
610dwarf_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
627static int
628attr_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
656static int
657initial_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
673static ptrdiff_t
674getlocations_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
731int
732dwarf_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
802ptrdiff_t
803dwarf_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