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