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