• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
817   *offset = start_offset;
818   return 0;
819 }
820 
821 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)822 getlocations_addr (Dwarf_Attribute *attr, ptrdiff_t offset,
823 		   Dwarf_Addr *basep, Dwarf_Addr *startp, Dwarf_Addr *endp,
824 		   Dwarf_Addr address, const Elf_Data *locs, Dwarf_Op **expr,
825 		   size_t *exprlen)
826 {
827   Dwarf_CU *cu = attr->cu;
828   Dwarf *dbg = cu->dbg;
829   size_t secidx = cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
830   const unsigned char *readp = locs->d_buf + offset;
831   const unsigned char *readendp = locs->d_buf + locs->d_size;
832 
833   Dwarf_Addr begin;
834   Dwarf_Addr end;
835 
836  next:
837   switch (__libdw_read_begin_end_pair_inc (cu, secidx,
838 					   &readp, readendp,
839 					   cu->address_size,
840 					   &begin, &end, basep))
841     {
842     case 0: /* got location range. */
843       break;
844     case 1: /* base address setup. */
845       goto next;
846     case 2: /* end of loclist */
847       return 0;
848     default: /* error */
849       return -1;
850     }
851 
852   /* We have a location expression.  */
853   Dwarf_Block block;
854   if (secidx == IDX_debug_loc)
855     {
856       if (readendp - readp < 2)
857 	{
858 	invalid:
859 	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
860 	  return -1;
861 	}
862       block.length = read_2ubyte_unaligned_inc (dbg, readp);
863     }
864   else
865     {
866       if (readendp - readp < 1)
867 	goto invalid;
868       get_uleb128 (block.length, readp, readendp);
869     }
870   block.data = (unsigned char *) readp;
871   if (readendp - readp < (ptrdiff_t) block.length)
872     goto invalid;
873   readp += block.length;
874 
875   /* Note these addresses include any base (if necessary) already.  */
876   *startp = begin;
877   *endp = end;
878 
879   /* If address is minus one we want them all, otherwise only matching.  */
880   if (address != (Dwarf_Word) -1 && (address < *startp || address >= *endp))
881     goto next;
882 
883   if (getlocation (cu, &block, expr, exprlen, secidx) != 0)
884     return -1;
885 
886   return readp - (unsigned char *) locs->d_buf;
887 }
888 
889 int
dwarf_getlocation_addr(Dwarf_Attribute * attr,Dwarf_Addr address,Dwarf_Op ** llbufs,size_t * listlens,size_t maxlocs)890 dwarf_getlocation_addr (Dwarf_Attribute *attr, Dwarf_Addr address,
891 			Dwarf_Op **llbufs, size_t *listlens, size_t maxlocs)
892 {
893   if (! attr_ok (attr))
894     return -1;
895 
896   if (llbufs == NULL)
897     maxlocs = SIZE_MAX;
898 
899   /* If it has a block form, it's a single location expression.
900      Except for DW_FORM_data16, which is a 128bit constant.  */
901   Dwarf_Block block;
902   if (attr->form != DW_FORM_data16
903       && INTUSE(dwarf_formblock) (attr, &block) == 0)
904     {
905       if (maxlocs == 0)
906 	return 0;
907       if (llbufs != NULL &&
908 	  getlocation (attr->cu, &block, &llbufs[0], &listlens[0],
909 		       cu_sec_idx (attr->cu)) != 0)
910 	return -1;
911       return listlens[0] == 0 ? 0 : 1;
912     }
913 
914   if (attr->form != DW_FORM_data16)
915     {
916       int error = INTUSE(dwarf_errno) ();
917       if (unlikely (error != DWARF_E_NO_BLOCK))
918 	{
919 	  __libdw_seterrno (error);
920 	  return -1;
921 	}
922     }
923 
924   /* If is_constant_offset is successful, we are done with 1 result.  */
925   int result = is_constant_offset (attr, llbufs, listlens);
926   if (result != 1)
927     return result ?: 1;
928 
929   Dwarf_Addr base, start, end;
930   Dwarf_Op *expr;
931   size_t expr_len;
932   ptrdiff_t off = 0;
933   size_t got = 0;
934 
935   /* This is a true loclistptr, fetch the initial base address and offset.  */
936   base = __libdw_cu_base_address (attr->cu);
937   if (base == (Dwarf_Addr) -1)
938     return -1;
939 
940   if (initial_offset (attr, &off) != 0)
941     return -1;
942 
943   size_t secidx = attr->cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
944   const Elf_Data *d = attr->cu->dbg->sectiondata[secidx];
945 
946   while (got < maxlocs
947          && (off = getlocations_addr (attr, off, &base, &start, &end,
948 				      address, d, &expr, &expr_len)) > 0)
949     {
950       /* This one matches the address.  */
951       if (llbufs != NULL)
952 	{
953 	  llbufs[got] = expr;
954 	  listlens[got] = expr_len;
955 	}
956       ++got;
957     }
958 
959   /* We might stop early, so off can be zero or positive on success.  */
960   if (off < 0)
961     return -1;
962 
963   return got;
964 }
965 
966 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)967 dwarf_getlocations (Dwarf_Attribute *attr, ptrdiff_t offset, Dwarf_Addr *basep,
968 		    Dwarf_Addr *startp, Dwarf_Addr *endp, Dwarf_Op **expr,
969 		    size_t *exprlen)
970 {
971   if (! attr_ok (attr))
972     return -1;
973 
974   /* 1 is an invalid offset, meaning no more locations. */
975   if (offset == 1)
976     return 0;
977 
978   if (offset == 0)
979     {
980       /* If it has a block form, it's a single location expression.
981 	 Except for DW_FORM_data16, which is a 128bit constant.  */
982       Dwarf_Block block;
983       if (attr->form != DW_FORM_data16
984 	  && INTUSE(dwarf_formblock) (attr, &block) == 0)
985 	{
986 	  if (getlocation (attr->cu, &block, expr, exprlen,
987 			   cu_sec_idx (attr->cu)) != 0)
988 	    return -1;
989 
990 	  /* This is the one and only location covering everything. */
991 	  *startp = 0;
992 	  *endp = -1;
993 	  return 1;
994 	}
995 
996       if (attr->form != DW_FORM_data16)
997 	{
998 	  int error = INTUSE(dwarf_errno) ();
999 	  if (unlikely (error != DWARF_E_NO_BLOCK))
1000 	    {
1001 	      __libdw_seterrno (error);
1002 	      return -1;
1003 	    }
1004 	}
1005 
1006       int result = is_constant_offset (attr, expr, exprlen);
1007       if (result != 1)
1008 	{
1009 	  if (result == 0)
1010 	    {
1011 	      /* This is the one and only location covering everything. */
1012 	      *startp = 0;
1013 	      *endp = -1;
1014 	      return 1;
1015 	    }
1016 	  return result; /* Something bad, dwarf_errno has been set.  */
1017 	}
1018 
1019       /* We must be looking at a true loclistptr, fetch the initial
1020 	 base address and offset.  */
1021       *basep = __libdw_cu_base_address (attr->cu);
1022       if (*basep == (Dwarf_Addr) -1)
1023 	return -1;
1024 
1025       if (initial_offset (attr, &offset) != 0)
1026 	return -1;
1027     }
1028 
1029   size_t secidx = attr->cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
1030   const Elf_Data *d = attr->cu->dbg->sectiondata[secidx];
1031 
1032   return getlocations_addr (attr, offset, basep, startp, endp,
1033 			    (Dwarf_Word) -1, d, expr, exprlen);
1034 }
1035