xref: /aosp_15_r20/external/elfutils/libdw/dwarf_getlocation.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1 /* Return location expression list.
2    Copyright (C) 2000-2010, 2013-2015, 2017, 2018 Red Hat, Inc.
3    This file is part of elfutils.
4 
5    This file is free software; you can redistribute it and/or modify
6    it under the terms of either
7 
8      * the GNU Lesser General Public License as published by the Free
9        Software Foundation; either version 3 of the License, or (at
10        your option) any later version
11 
12    or
13 
14      * the GNU General Public License as published by the Free
15        Software Foundation; either version 2 of the License, or (at
16        your option) any later version
17 
18    or both in parallel, as here.
19 
20    elfutils is distributed in the hope that it will be useful, but
21    WITHOUT ANY WARRANTY; without even the implied warranty of
22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23    General Public License for more details.
24 
25    You should have received copies of the GNU General Public License and
26    the GNU Lesser General Public License along with this program.  If
27    not, see <http://www.gnu.org/licenses/>.  */
28 
29 #ifdef HAVE_CONFIG_H
30 # include <config.h>
31 #endif
32 
33 #include <dwarf.h>
34 #include <search.h>
35 #include <stdlib.h>
36 #include <assert.h>
37 
38 #include <libdwP.h>
39 
40 
41 static bool
attr_ok(Dwarf_Attribute * attr)42 attr_ok (Dwarf_Attribute *attr)
43 {
44   if (attr == NULL)
45     return false;
46 
47   /* If it is an exprloc, it is obviously OK.  */
48   if (dwarf_whatform (attr) == DW_FORM_exprloc)
49     return true;
50 
51   if (attr->cu->version >= 4)
52     {
53       /* Must be an exprloc (or constant), just not any block form.  */
54       switch (dwarf_whatform (attr))
55 	{
56 	case DW_FORM_block:
57 	case DW_FORM_block1:
58 	case DW_FORM_block2:
59 	case DW_FORM_block4:
60 	  __libdw_seterrno (DWARF_E_NO_LOC_VALUE);
61 	  return false;
62 	default:
63 	  break;
64 	}
65     }
66 
67   /* Otherwise must be one of the attributes listed below.  Older
68      DWARF versions might have encoded the exprloc as block, and we
69      cannot easily distinguish attributes in the loclist class because
70      the same forms are used for different classes.  */
71   switch (attr->code)
72     {
73     case DW_AT_location:
74     case DW_AT_byte_size:
75     case DW_AT_bit_offset:
76     case DW_AT_bit_size:
77     case DW_AT_lower_bound:
78     case DW_AT_bit_stride:
79     case DW_AT_upper_bound:
80     case DW_AT_count:
81     case DW_AT_allocated:
82     case DW_AT_associated:
83     case DW_AT_data_location:
84     case DW_AT_byte_stride:
85     case DW_AT_rank:
86     case DW_AT_call_value:
87     case DW_AT_call_target:
88     case DW_AT_call_target_clobbered:
89     case DW_AT_call_data_location:
90     case DW_AT_call_data_value:
91     case DW_AT_data_member_location:
92     case DW_AT_vtable_elem_location:
93     case DW_AT_string_length:
94     case DW_AT_use_location:
95     case DW_AT_frame_base:
96     case DW_AT_return_addr:
97     case DW_AT_static_link:
98     case DW_AT_segment:
99     case DW_AT_GNU_call_site_value:
100     case DW_AT_GNU_call_site_data_value:
101     case DW_AT_GNU_call_site_target:
102     case DW_AT_GNU_call_site_target_clobbered:
103       break;
104 
105     default:
106       __libdw_seterrno (DWARF_E_NO_LOC_VALUE);
107       return false;
108     }
109 
110   return true;
111 }
112 
113 
114 struct loclist
115 {
116   uint8_t atom;
117   Dwarf_Word number;
118   Dwarf_Word number2;
119   Dwarf_Word offset;
120   struct loclist *next;
121 };
122 
123 
124 static int
loc_compare(const void * p1,const void * p2)125 loc_compare (const void *p1, const void *p2)
126 {
127   const struct loc_s *l1 = (const struct loc_s *) p1;
128   const struct loc_s *l2 = (const struct loc_s *) p2;
129 
130   if ((uintptr_t) l1->addr < (uintptr_t) l2->addr)
131     return -1;
132   if ((uintptr_t) l1->addr > (uintptr_t) l2->addr)
133     return 1;
134 
135   return 0;
136 }
137 
138 /* For each DW_OP_implicit_value, we store a special entry in the cache.
139    This points us directly to the block data for later fetching.
140    Returns zero on success, -1 on bad DWARF or 1 if tsearch failed.  */
141 static int
store_implicit_value(Dwarf * dbg,void ** cache,Dwarf_Op * op)142 store_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op)
143 {
144   if (dbg == NULL)
145     return -1;
146   struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s,
147 					   sizeof (struct loc_block_s), 1);
148   const unsigned char *data = (const unsigned char *) (uintptr_t) op->number2;
149   /* Skip the block length.  */
150   Dwarf_Word length;
151   get_uleb128_unchecked (length, data);
152   if (length != op->number)
153     return -1;
154   block->addr = op;
155   block->data = (unsigned char *) data;
156   block->length = op->number;
157   if (unlikely (tsearch (block, cache, loc_compare) == NULL))
158     return 1;
159   return 0;
160 }
161 
162 int
dwarf_getlocation_implicit_value(Dwarf_Attribute * attr,const Dwarf_Op * op,Dwarf_Block * return_block)163 dwarf_getlocation_implicit_value (Dwarf_Attribute *attr, const Dwarf_Op *op,
164 				  Dwarf_Block *return_block)
165 {
166   if (attr == NULL)
167     return -1;
168 
169   struct loc_block_s fake = { .addr = (void *) op };
170   struct loc_block_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
171   if (unlikely (found == NULL))
172     {
173       __libdw_seterrno (DWARF_E_NO_BLOCK);
174       return -1;
175     }
176 
177   return_block->length = (*found)->length;
178   return_block->data = (*found)->data;
179   return 0;
180 }
181 
182 /* If the given attribute is DW_AT_data_member_location and it has constant
183    form then create a fake location using DW_OP_plus_uconst and the offset
184    value.  On success returns zero and fills in llbuf (when not NULL) and
185    sets listlen to 1.  Returns 1 when this isn't a DW_AT_data_member_location
186    offset.  Returns -1 and sets dwarf_errno on failure (bad DWARF data).  */
187 static int
is_constant_offset(Dwarf_Attribute * attr,Dwarf_Op ** llbuf,size_t * listlen)188 is_constant_offset (Dwarf_Attribute *attr,
189 		    Dwarf_Op **llbuf, size_t *listlen)
190 {
191   if (attr->code != DW_AT_data_member_location)
192     return 1;
193 
194   switch (attr->form)
195     {
196       /* Punt for any non-constant form.  */
197     default:
198       return 1;
199 
200       /* Note, we don't regard DW_FORM_data16 as a constant form,
201 	 even though technically it is according to the standard.  */
202     case DW_FORM_data1:
203     case DW_FORM_data2:
204     case DW_FORM_data4:
205     case DW_FORM_data8:
206     case DW_FORM_sdata:
207     case DW_FORM_udata:
208     case DW_FORM_implicit_const:
209       break;
210     }
211 
212   /* Check whether we already cached this location.  */
213   struct loc_s fake = { .addr = attr->valp };
214   struct loc_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
215 
216   if (found == NULL)
217     {
218       Dwarf_Word offset;
219       if (INTUSE(dwarf_formudata) (attr, &offset) != 0)
220 	return -1;
221 
222       Dwarf_Op *result = libdw_alloc (attr->cu->dbg,
223 				      Dwarf_Op, sizeof (Dwarf_Op), 1);
224 
225       result->atom = DW_OP_plus_uconst;
226       result->number = offset;
227       result->number2 = 0;
228       result->offset = 0;
229 
230       /* Insert a record in the search tree so we can find it again later.  */
231       struct loc_s *newp = libdw_alloc (attr->cu->dbg,
232 					struct loc_s, sizeof (struct loc_s),
233 					1);
234       newp->addr = attr->valp;
235       newp->loc = result;
236       newp->nloc = 1;
237 
238       found = tsearch (newp, &attr->cu->locs, loc_compare);
239     }
240 
241   assert ((*found)->nloc == 1);
242 
243   if (llbuf != NULL)
244     {
245       *llbuf = (*found)->loc;
246       *listlen = 1;
247     }
248 
249   return 0;
250 }
251 
252 int
253 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)254 __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
255 			   unsigned int address_size, unsigned int ref_size,
256 			   void **cache, const Dwarf_Block *block,
257 			   bool cfap, bool valuep,
258 			   Dwarf_Op **llbuf, size_t *listlen, int sec_index)
259 {
260   /* Empty location expressions don't have any ops to intern.  */
261   if (block->length == 0)
262     {
263       *listlen = 0;
264       return 0;
265     }
266 
267   /* Check whether we already looked at this list.  */
268   struct loc_s fake = { .addr = block->data };
269   struct loc_s **found = tfind (&fake, cache, loc_compare);
270   if (found != NULL)
271     {
272       /* We already saw it.  */
273       *llbuf = (*found)->loc;
274       *listlen = (*found)->nloc;
275 
276       if (valuep)
277 	{
278 	  assert (*listlen > 1);
279 	  assert ((*llbuf)[*listlen - 1].atom == DW_OP_stack_value);
280 	}
281 
282       return 0;
283     }
284 
285   const unsigned char *data = block->data;
286   const unsigned char *const end_data = data + block->length;
287 
288   const struct { bool other_byte_order; } bo = { other_byte_order };
289 
290   struct loclist *loclist = NULL;
291   unsigned int n = 0;
292 
293   /* Stack allocate at most this many locs.  */
294 #define MAX_STACK_LOCS 256
295   struct loclist stack_locs[MAX_STACK_LOCS];
296 #define NEW_LOC() ({ struct loclist *ll;			\
297 		     ll = (likely (n < MAX_STACK_LOCS)		\
298 			   ? &stack_locs[n]			\
299 			   : malloc (sizeof (struct loclist)));	\
300 		     if (unlikely (ll == NULL))			\
301 		       goto nomem;				\
302 		     n++;					\
303 		     ll->next = loclist;			\
304 		     loclist = ll;				\
305 		     ll; })
306 
307   if (cfap)
308     {
309       /* Synthesize the operation to push the CFA before the expression.  */
310       struct loclist *newloc = NEW_LOC ();
311       newloc->atom = DW_OP_call_frame_cfa;
312       newloc->number = 0;
313       newloc->number2 = 0;
314       newloc->offset = -1;
315     }
316 
317   /* Decode the opcodes.  It is possible in some situations to have a
318      block of size zero.  */
319   while (data < end_data)
320     {
321       struct loclist *newloc;
322       newloc = NEW_LOC ();
323       newloc->number = 0;
324       newloc->number2 = 0;
325       newloc->offset = data - block->data;
326 
327       switch ((newloc->atom = *data++))
328 	{
329 	case DW_OP_addr:
330 	  /* Address, depends on address size of CU.  */
331 	  if (dbg == NULL)
332 	    {
333 	      // XXX relocation?
334 	      if (address_size == 4)
335 		{
336 		  if (unlikely (data + 4 > end_data))
337 		    goto invalid;
338 		  else
339 		    newloc->number = read_4ubyte_unaligned_inc (&bo, data);
340 		}
341 	      else
342 		{
343 		  if (unlikely (data + 8 > end_data))
344 		    goto invalid;
345 		  else
346 		    newloc->number = read_8ubyte_unaligned_inc (&bo, data);
347 		}
348 	    }
349 	  else if (__libdw_read_address_inc (dbg, sec_index, &data,
350 					     address_size, &newloc->number))
351 	    goto invalid;
352 	  break;
353 
354 	case DW_OP_call_ref:
355 	case DW_OP_GNU_variable_value:
356 	  /* DW_FORM_ref_addr, depends on offset size of CU.  */
357 	  if (dbg == NULL || __libdw_read_offset_inc (dbg, sec_index, &data,
358 						      ref_size,
359 						      &newloc->number,
360 						      IDX_debug_info, 0))
361 	    goto invalid;
362 	  break;
363 
364 	case DW_OP_deref:
365 	case DW_OP_dup:
366 	case DW_OP_drop:
367 	case DW_OP_over:
368 	case DW_OP_swap:
369 	case DW_OP_rot:
370 	case DW_OP_xderef:
371 	case DW_OP_abs:
372 	case DW_OP_and:
373 	case DW_OP_div:
374 	case DW_OP_minus:
375 	case DW_OP_mod:
376 	case DW_OP_mul:
377 	case DW_OP_neg:
378 	case DW_OP_not:
379 	case DW_OP_or:
380 	case DW_OP_plus:
381 	case DW_OP_shl:
382 	case DW_OP_shr:
383 	case DW_OP_shra:
384 	case DW_OP_xor:
385 	case DW_OP_eq:
386 	case DW_OP_ge:
387 	case DW_OP_gt:
388 	case DW_OP_le:
389 	case DW_OP_lt:
390 	case DW_OP_ne:
391 	case DW_OP_lit0 ... DW_OP_lit31:
392 	case DW_OP_reg0 ... DW_OP_reg31:
393 	case DW_OP_nop:
394 	case DW_OP_push_object_address:
395 	case DW_OP_call_frame_cfa:
396 	case DW_OP_form_tls_address:
397 	case DW_OP_GNU_push_tls_address:
398 	case DW_OP_stack_value:
399 	case DW_OP_GNU_uninit:
400 	  /* No operand.  */
401 	  break;
402 
403 	case DW_OP_const1u:
404 	case DW_OP_pick:
405 	case DW_OP_deref_size:
406 	case DW_OP_xderef_size:
407 	  if (unlikely (data >= end_data))
408 	    {
409 	    invalid:
410 	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
411 	    returnmem:
412 	      /* Free any dynamically allocated loclists, if any.  */
413 	      while (n > MAX_STACK_LOCS)
414 		{
415 		  struct loclist *loc = loclist;
416 		  loclist = loc->next;
417 		  free (loc);
418 		  n--;
419 		}
420 	      return -1;
421 	    }
422 
423 	  newloc->number = *data++;
424 	  break;
425 
426 	case DW_OP_const1s:
427 	  if (unlikely (data >= end_data))
428 	    goto invalid;
429 
430 	  newloc->number = *((int8_t *) data);
431 	  ++data;
432 	  break;
433 
434 	case DW_OP_const2u:
435 	  if (unlikely (data + 2 > end_data))
436 	    goto invalid;
437 
438 	  newloc->number = read_2ubyte_unaligned_inc (&bo, data);
439 	  break;
440 
441 	case DW_OP_const2s:
442 	case DW_OP_skip:
443 	case DW_OP_bra:
444 	case DW_OP_call2:
445 	  if (unlikely (data + 2 > end_data))
446 	    goto invalid;
447 
448 	  newloc->number = read_2sbyte_unaligned_inc (&bo, data);
449 	  break;
450 
451 	case DW_OP_const4u:
452 	  if (unlikely (data + 4 > end_data))
453 	    goto invalid;
454 
455 	  newloc->number = read_4ubyte_unaligned_inc (&bo, data);
456 	  break;
457 
458 	case DW_OP_const4s:
459 	case DW_OP_call4:
460 	case DW_OP_GNU_parameter_ref:
461 	  if (unlikely (data + 4 > end_data))
462 	    goto invalid;
463 
464 	  newloc->number = read_4sbyte_unaligned_inc (&bo, data);
465 	  break;
466 
467 	case DW_OP_const8u:
468 	  if (unlikely (data + 8 > end_data))
469 	    goto invalid;
470 
471 	  newloc->number = read_8ubyte_unaligned_inc (&bo, data);
472 	  break;
473 
474 	case DW_OP_const8s:
475 	  if (unlikely (data + 8 > end_data))
476 	    goto invalid;
477 
478 	  newloc->number = read_8sbyte_unaligned_inc (&bo, data);
479 	  break;
480 
481 	case DW_OP_constu:
482 	case DW_OP_plus_uconst:
483 	case DW_OP_regx:
484 	case DW_OP_piece:
485 	case DW_OP_convert:
486 	case DW_OP_GNU_convert:
487 	case DW_OP_reinterpret:
488 	case DW_OP_GNU_reinterpret:
489 	case DW_OP_addrx:
490 	case DW_OP_GNU_addr_index:
491 	case DW_OP_constx:
492 	case DW_OP_GNU_const_index:
493 	  get_uleb128 (newloc->number, data, end_data);
494 	  break;
495 
496 	case DW_OP_consts:
497 	case DW_OP_breg0 ... DW_OP_breg31:
498 	case DW_OP_fbreg:
499 	  get_sleb128 (newloc->number, data, end_data);
500 	  break;
501 
502 	case DW_OP_bregx:
503 	  get_uleb128 (newloc->number, data, end_data);
504 	  if (unlikely (data >= end_data))
505 	    goto invalid;
506 	  get_sleb128 (newloc->number2, data, end_data);
507 	  break;
508 
509 	case DW_OP_bit_piece:
510 	case DW_OP_regval_type:
511 	case DW_OP_GNU_regval_type:
512 	  get_uleb128 (newloc->number, data, end_data);
513 	  if (unlikely (data >= end_data))
514 	    goto invalid;
515 	  get_uleb128 (newloc->number2, data, end_data);
516 	  break;
517 
518 	case DW_OP_implicit_value:
519 	case DW_OP_entry_value:
520 	case DW_OP_GNU_entry_value:
521 	  /* This cannot be used in a CFI expression.  */
522 	  if (unlikely (dbg == NULL))
523 	    goto invalid;
524 
525 	  /* start of block inc. len.  */
526 	  newloc->number2 = (Dwarf_Word) (uintptr_t) data;
527 	  get_uleb128 (newloc->number, data, end_data); /* Block length.  */
528 	  if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number))
529 	    goto invalid;
530 	  data += newloc->number;		/* Skip the block.  */
531 	  break;
532 
533 	case DW_OP_implicit_pointer:
534 	case DW_OP_GNU_implicit_pointer:
535 	  /* DW_FORM_ref_addr, depends on offset size of CU.  */
536 	  if (dbg == NULL || __libdw_read_offset_inc (dbg, sec_index, &data,
537 						      ref_size,
538 						      &newloc->number,
539 						      IDX_debug_info, 0))
540 	    goto invalid;
541 	  if (unlikely (data >= end_data))
542 	    goto invalid;
543 	  get_uleb128 (newloc->number2, data, end_data); /* Byte offset.  */
544 	  break;
545 
546 	case DW_OP_deref_type:
547 	case DW_OP_GNU_deref_type:
548 	case DW_OP_xderef_type:
549 	  if (unlikely (data + 1 >= end_data))
550 	    goto invalid;
551 	  newloc->number = *data++;
552 	  get_uleb128 (newloc->number2, data, end_data);
553 	  break;
554 
555 	case DW_OP_const_type:
556 	case DW_OP_GNU_const_type:
557 	  {
558 	    size_t size;
559 	    get_uleb128 (newloc->number, data, end_data);
560 	    if (unlikely (data >= end_data))
561 	      goto invalid;
562 
563 	    /* start of block inc. len.  */
564 	    newloc->number2 = (Dwarf_Word) (uintptr_t) data;
565 	    size = *data++;
566 	    if (unlikely ((Dwarf_Word) (end_data - data) < size))
567 	      goto invalid;
568 	    data += size;		/* Skip the block.  */
569 	  }
570 	  break;
571 
572 	default:
573 	  goto invalid;
574 	}
575     }
576 
577   if (unlikely (n == 0))
578     {
579       /* This is not allowed.
580 	 It would mean an empty location expression, which we handled
581 	 already as a special case above.  */
582       goto invalid;
583     }
584 
585   if (valuep)
586     {
587       struct loclist *newloc = NEW_LOC ();
588       newloc->atom = DW_OP_stack_value;
589       newloc->number = 0;
590       newloc->number2 = 0;
591       newloc->offset = data - block->data;
592     }
593 
594   /* Allocate the array.  */
595   Dwarf_Op *result;
596   if (dbg != NULL)
597     result = libdw_alloc (dbg, Dwarf_Op, sizeof (Dwarf_Op), n);
598   else
599     {
600       result = malloc (sizeof *result * n);
601       if (result == NULL)
602 	{
603 	nomem:
604 	  __libdw_seterrno (DWARF_E_NOMEM);
605 	  goto returnmem;
606 	}
607     }
608 
609   /* Store the result.  */
610   *llbuf = result;
611   *listlen = n;
612 
613   do
614     {
615       /* We populate the array from the back since the list is backwards.  */
616       --n;
617       result[n].atom = loclist->atom;
618       result[n].number = loclist->number;
619       result[n].number2 = loclist->number2;
620       result[n].offset = loclist->offset;
621 
622       if (result[n].atom == DW_OP_implicit_value)
623 	{
624 	  int store = store_implicit_value (dbg, cache, &result[n]);
625 	  if (unlikely (store != 0))
626 	    {
627 	      if (store < 0)
628 	        goto invalid;
629 	      else
630 		goto nomem;
631 	    }
632 	}
633 
634       struct loclist *loc = loclist;
635       loclist = loclist->next;
636       if (unlikely (n + 1 > MAX_STACK_LOCS))
637 	free (loc);
638     }
639   while (n > 0);
640 
641   /* Insert a record in the search tree so that we can find it again later.  */
642   struct loc_s *newp;
643   if (dbg != NULL)
644     newp = libdw_alloc (dbg, struct loc_s, sizeof (struct loc_s), 1);
645   else
646     {
647       newp = malloc (sizeof *newp);
648       if (newp == NULL)
649 	{
650 	  free (result);
651 	  goto nomem;
652 	}
653     }
654 
655   newp->addr = block->data;
656   newp->loc = result;
657   newp->nloc = *listlen;
658   (void) tsearch (newp, cache, loc_compare);
659 
660   /* We did it.  */
661   return 0;
662 }
663 
664 static int
getlocation(struct Dwarf_CU * cu,const Dwarf_Block * block,Dwarf_Op ** llbuf,size_t * listlen,int sec_index)665 getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
666 	     Dwarf_Op **llbuf, size_t *listlen, int sec_index)
667 {
668   /* Empty location expressions don't have any ops to intern.
669      Note that synthetic empty_cu doesn't have an associated DWARF dbg.  */
670   if (block->length == 0)
671     {
672       *listlen = 0;
673       return 0;
674     }
675 
676   return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order,
677 				    cu->address_size, (cu->version == 2
678 						       ? cu->address_size
679 						       : cu->offset_size),
680 				    &cu->locs, block,
681 				    false, false,
682 				    llbuf, listlen, sec_index);
683 }
684 
685 int
dwarf_getlocation(Dwarf_Attribute * attr,Dwarf_Op ** llbuf,size_t * listlen)686 dwarf_getlocation (Dwarf_Attribute *attr, Dwarf_Op **llbuf, size_t *listlen)
687 {
688   if (! attr_ok (attr))
689     return -1;
690 
691   int result = is_constant_offset (attr, llbuf, listlen);
692   if (result != 1)
693     return result; /* Either success 0, or -1 to indicate error.  */
694 
695   /* If it has a block form, it's a single location expression.
696      Except for DW_FORM_data16, which is a 128bit constant.  */
697   if (attr->form == DW_FORM_data16)
698     {
699       __libdw_seterrno (DWARF_E_NO_BLOCK);
700       return -1;
701     }
702   Dwarf_Block block;
703   if (INTUSE(dwarf_formblock) (attr, &block) != 0)
704     return -1;
705 
706   return getlocation (attr->cu, &block, llbuf, listlen, cu_sec_idx (attr->cu));
707 }
708 
709 Dwarf_Addr
__libdw_cu_base_address(Dwarf_CU * cu)710 __libdw_cu_base_address (Dwarf_CU *cu)
711 {
712   if (cu->base_address == (Dwarf_Addr) -1)
713     {
714       Dwarf_Addr base;
715 
716       /* Fetch the CU's base address.  */
717       Dwarf_Die cudie = CUDIE (cu);
718 
719       /* Find the base address of the compilation unit.  It will
720 	 normally be specified by DW_AT_low_pc.  In DWARF-3 draft 4,
721 	 the base address could be overridden by DW_AT_entry_pc.  It's
722 	 been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc
723 	 for compilation units with discontinuous ranges.  */
724       Dwarf_Attribute attr_mem;
725       if (INTUSE(dwarf_lowpc) (&cudie, &base) != 0
726 	  && INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (&cudie,
727 							 DW_AT_entry_pc,
728 							 &attr_mem),
729 				     &base) != 0)
730 	{
731 	  /* The compiler provided no base address when it should
732 	     have.  Buggy GCC does this when it used absolute
733 	     addresses in the location list and no DW_AT_ranges.  */
734 	   base = 0;
735 	}
736       cu->base_address = base;
737     }
738 
739   return cu->base_address;
740 }
741 
742 static int
initial_offset(Dwarf_Attribute * attr,ptrdiff_t * offset)743 initial_offset (Dwarf_Attribute *attr, ptrdiff_t *offset)
744 {
745   size_t secidx = (attr->cu->version < 5
746 		   ? IDX_debug_loc : IDX_debug_loclists);
747 
748   Dwarf_Word start_offset;
749   if (attr->form == DW_FORM_loclistx)
750     {
751       Dwarf_Word idx;
752       Dwarf_CU *cu = attr->cu;
753       const unsigned char *datap = attr->valp;
754       const unsigned char *endp = cu->endp;
755       if (datap >= endp)
756 	{
757 	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
758 	  return -1;
759 	}
760       get_uleb128 (idx, datap, endp);
761 
762       Elf_Data *data = cu->dbg->sectiondata[secidx];
763       if (data == NULL && cu->unit_type == DW_UT_split_compile)
764 	{
765 	  cu = __libdw_find_split_unit (cu);
766 	  if (cu != NULL)
767 	    data = cu->dbg->sectiondata[secidx];
768 	}
769 
770       if (data == NULL)
771 	{
772 	  __libdw_seterrno (secidx == IDX_debug_loc
773                             ? DWARF_E_NO_DEBUG_LOC
774                             : DWARF_E_NO_DEBUG_LOCLISTS);
775 	  return -1;
776 	}
777 
778       Dwarf_Off loc_base_off = __libdw_cu_locs_base (cu);
779 
780       /* The section should at least contain room for one offset.  */
781       size_t sec_size = cu->dbg->sectiondata[secidx]->d_size;
782       size_t offset_size = cu->offset_size;
783       if (offset_size > sec_size)
784 	{
785 	invalid_offset:
786 	  __libdw_seterrno (DWARF_E_INVALID_OFFSET);
787 	  return -1;
788 	}
789 
790       /* And the base offset should be at least inside the section.  */
791       if (loc_base_off > (sec_size - offset_size))
792 	goto invalid_offset;
793 
794       size_t max_idx = (sec_size - offset_size - loc_base_off) / offset_size;
795       if (idx > max_idx)
796 	goto invalid_offset;
797 
798       datap = (cu->dbg->sectiondata[secidx]->d_buf
799 	       + loc_base_off + (idx * offset_size));
800       if (offset_size == 4)
801 	start_offset = read_4ubyte_unaligned (cu->dbg, datap);
802       else
803 	start_offset = read_8ubyte_unaligned (cu->dbg, datap);
804 
805       start_offset += loc_base_off;
806     }
807   else
808     {
809       if (__libdw_formptr (attr, secidx,
810 			   (secidx == IDX_debug_loc
811 			    ? DWARF_E_NO_DEBUG_LOC
812 			    : DWARF_E_NO_DEBUG_LOCLISTS),
813 			    NULL, &start_offset) == NULL)
814 	return -1;
815 
816       Dwarf_Off loc_off;
817       if (INTUSE(dwarf_cu_dwp_section_info) (attr->cu, DW_SECT_LOCLISTS,
818 					     &loc_off, NULL) != 0)
819 	return -1;
820       start_offset += loc_off;
821     }
822 
823   *offset = start_offset;
824   return 0;
825 }
826 
827 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)828 getlocations_addr (Dwarf_Attribute *attr, ptrdiff_t offset,
829 		   Dwarf_Addr *basep, Dwarf_Addr *startp, Dwarf_Addr *endp,
830 		   Dwarf_Addr address, const Elf_Data *locs, Dwarf_Op **expr,
831 		   size_t *exprlen)
832 {
833   Dwarf_CU *cu = attr->cu;
834   Dwarf *dbg = cu->dbg;
835   size_t secidx = cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
836   const unsigned char *readp = locs->d_buf + offset;
837   const unsigned char *readendp = locs->d_buf + locs->d_size;
838 
839   Dwarf_Addr begin;
840   Dwarf_Addr end;
841 
842  next:
843   switch (__libdw_read_begin_end_pair_inc (cu, secidx,
844 					   &readp, readendp,
845 					   cu->address_size,
846 					   &begin, &end, basep))
847     {
848     case 0: /* got location range. */
849       break;
850     case 1: /* base address setup. */
851       goto next;
852     case 2: /* end of loclist */
853       return 0;
854     default: /* error */
855       return -1;
856     }
857 
858   /* We have a location expression.  */
859   Dwarf_Block block;
860   if (secidx == IDX_debug_loc)
861     {
862       if (readendp - readp < 2)
863 	{
864 	invalid:
865 	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
866 	  return -1;
867 	}
868       block.length = read_2ubyte_unaligned_inc (dbg, readp);
869     }
870   else
871     {
872       if (readendp - readp < 1)
873 	goto invalid;
874       get_uleb128 (block.length, readp, readendp);
875     }
876   block.data = (unsigned char *) readp;
877   if (readendp - readp < (ptrdiff_t) block.length)
878     goto invalid;
879   readp += block.length;
880 
881   /* Note these addresses include any base (if necessary) already.  */
882   *startp = begin;
883   *endp = end;
884 
885   /* If address is minus one we want them all, otherwise only matching.  */
886   if (address != (Dwarf_Word) -1 && (address < *startp || address >= *endp))
887     goto next;
888 
889   if (getlocation (cu, &block, expr, exprlen, secidx) != 0)
890     return -1;
891 
892   return readp - (unsigned char *) locs->d_buf;
893 }
894 
895 int
dwarf_getlocation_addr(Dwarf_Attribute * attr,Dwarf_Addr address,Dwarf_Op ** llbufs,size_t * listlens,size_t maxlocs)896 dwarf_getlocation_addr (Dwarf_Attribute *attr, Dwarf_Addr address,
897 			Dwarf_Op **llbufs, size_t *listlens, size_t maxlocs)
898 {
899   if (! attr_ok (attr))
900     return -1;
901 
902   if (llbufs == NULL)
903     maxlocs = SIZE_MAX;
904 
905   /* If it has a block form, it's a single location expression.
906      Except for DW_FORM_data16, which is a 128bit constant.  */
907   Dwarf_Block block;
908   if (attr->form != DW_FORM_data16
909       && INTUSE(dwarf_formblock) (attr, &block) == 0)
910     {
911       if (maxlocs == 0)
912 	return 0;
913       if (llbufs != NULL &&
914 	  getlocation (attr->cu, &block, &llbufs[0], &listlens[0],
915 		       cu_sec_idx (attr->cu)) != 0)
916 	return -1;
917       return listlens[0] == 0 ? 0 : 1;
918     }
919 
920   if (attr->form != DW_FORM_data16)
921     {
922       int error = INTUSE(dwarf_errno) ();
923       if (unlikely (error != DWARF_E_NO_BLOCK))
924 	{
925 	  __libdw_seterrno (error);
926 	  return -1;
927 	}
928     }
929 
930   /* If is_constant_offset is successful, we are done with 1 result.  */
931   int result = is_constant_offset (attr, llbufs, listlens);
932   if (result != 1)
933     return result ?: 1;
934 
935   Dwarf_Addr base, start, end;
936   Dwarf_Op *expr;
937   size_t expr_len;
938   ptrdiff_t off = 0;
939   size_t got = 0;
940 
941   /* This is a true loclistptr, fetch the initial base address and offset.  */
942   base = __libdw_cu_base_address (attr->cu);
943   if (base == (Dwarf_Addr) -1)
944     return -1;
945 
946   if (initial_offset (attr, &off) != 0)
947     return -1;
948 
949   size_t secidx = attr->cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
950   const Elf_Data *d = attr->cu->dbg->sectiondata[secidx];
951 
952   while (got < maxlocs
953          && (off = getlocations_addr (attr, off, &base, &start, &end,
954 				      address, d, &expr, &expr_len)) > 0)
955     {
956       /* This one matches the address.  */
957       if (llbufs != NULL)
958 	{
959 	  llbufs[got] = expr;
960 	  listlens[got] = expr_len;
961 	}
962       ++got;
963     }
964 
965   /* We might stop early, so off can be zero or positive on success.  */
966   if (off < 0)
967     return -1;
968 
969   return got;
970 }
971 
972 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)973 dwarf_getlocations (Dwarf_Attribute *attr, ptrdiff_t offset, Dwarf_Addr *basep,
974 		    Dwarf_Addr *startp, Dwarf_Addr *endp, Dwarf_Op **expr,
975 		    size_t *exprlen)
976 {
977   if (! attr_ok (attr))
978     return -1;
979 
980   /* 1 is an invalid offset, meaning no more locations. */
981   if (offset == 1)
982     return 0;
983 
984   if (offset == 0)
985     {
986       /* If it has a block form, it's a single location expression.
987 	 Except for DW_FORM_data16, which is a 128bit constant.  */
988       Dwarf_Block block;
989       if (attr->form != DW_FORM_data16
990 	  && INTUSE(dwarf_formblock) (attr, &block) == 0)
991 	{
992 	  if (getlocation (attr->cu, &block, expr, exprlen,
993 			   cu_sec_idx (attr->cu)) != 0)
994 	    return -1;
995 
996 	  /* This is the one and only location covering everything. */
997 	  *startp = 0;
998 	  *endp = -1;
999 	  return 1;
1000 	}
1001 
1002       if (attr->form != DW_FORM_data16)
1003 	{
1004 	  int error = INTUSE(dwarf_errno) ();
1005 	  if (unlikely (error != DWARF_E_NO_BLOCK))
1006 	    {
1007 	      __libdw_seterrno (error);
1008 	      return -1;
1009 	    }
1010 	}
1011 
1012       int result = is_constant_offset (attr, expr, exprlen);
1013       if (result != 1)
1014 	{
1015 	  if (result == 0)
1016 	    {
1017 	      /* This is the one and only location covering everything. */
1018 	      *startp = 0;
1019 	      *endp = -1;
1020 	      return 1;
1021 	    }
1022 	  return result; /* Something bad, dwarf_errno has been set.  */
1023 	}
1024 
1025       /* We must be looking at a true loclistptr, fetch the initial
1026 	 base address and offset.  */
1027       *basep = __libdw_cu_base_address (attr->cu);
1028       if (*basep == (Dwarf_Addr) -1)
1029 	return -1;
1030 
1031       if (initial_offset (attr, &offset) != 0)
1032 	return -1;
1033     }
1034 
1035   size_t secidx = attr->cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
1036   const Elf_Data *d = attr->cu->dbg->sectiondata[secidx];
1037 
1038   return getlocations_addr (attr, offset, basep, startp, endp,
1039 			    (Dwarf_Word) -1, d, expr, exprlen);
1040 }
1041