• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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(Dwarf_Attribute * attr,const Dwarf_Op * op,Dwarf_Block * return_block)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
check_constant_offset(Dwarf_Attribute * attr,Dwarf_Op ** llbuf,size_t * listlen)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
__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)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
getlocation(struct Dwarf_CU * cu,const Dwarf_Block * block,Dwarf_Op ** llbuf,size_t * listlen,int sec_index)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
dwarf_getlocation(Dwarf_Attribute * attr,Dwarf_Op ** llbuf,size_t * listlen)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
attr_base_address(Dwarf_Attribute * attr,Dwarf_Addr * basep)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
initial_offset_base(Dwarf_Attribute * attr,ptrdiff_t * offset,Dwarf_Addr * basep)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
getlocations_addr(Dwarf_Attribute * attr,ptrdiff_t offset,Dwarf_Addr * basep,Dwarf_Addr * startp,Dwarf_Addr * endp,Dwarf_Addr address,const Elf_Data * locs,Dwarf_Op ** expr,size_t * exprlen)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
dwarf_getlocation_addr(Dwarf_Attribute * attr,Dwarf_Addr address,Dwarf_Op ** llbufs,size_t * listlens,size_t maxlocs)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
dwarf_getlocations(Dwarf_Attribute * attr,ptrdiff_t offset,Dwarf_Addr * basep,Dwarf_Addr * startp,Dwarf_Addr * endp,Dwarf_Op ** expr,size_t * exprlen)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