• 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 	  /* No operand.  */
400 	  break;
401 
402 	case DW_OP_const1u:
403 	case DW_OP_pick:
404 	case DW_OP_deref_size:
405 	case DW_OP_xderef_size:
406 	  if (unlikely (data >= end_data))
407 	    {
408 	    invalid:
409 	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
410 	    returnmem:
411 	      /* Free any dynamically allocated loclists, if any.  */
412 	      while (n > MAX_STACK_LOCS)
413 		{
414 		  struct loclist *loc = loclist;
415 		  loclist = loc->next;
416 		  free (loc);
417 		  n--;
418 		}
419 	      return -1;
420 	    }
421 
422 	  newloc->number = *data++;
423 	  break;
424 
425 	case DW_OP_const1s:
426 	  if (unlikely (data >= end_data))
427 	    goto invalid;
428 
429 	  newloc->number = *((int8_t *) data);
430 	  ++data;
431 	  break;
432 
433 	case DW_OP_const2u:
434 	  if (unlikely (data + 2 > end_data))
435 	    goto invalid;
436 
437 	  newloc->number = read_2ubyte_unaligned_inc (&bo, data);
438 	  break;
439 
440 	case DW_OP_const2s:
441 	case DW_OP_skip:
442 	case DW_OP_bra:
443 	case DW_OP_call2:
444 	  if (unlikely (data + 2 > end_data))
445 	    goto invalid;
446 
447 	  newloc->number = read_2sbyte_unaligned_inc (&bo, data);
448 	  break;
449 
450 	case DW_OP_const4u:
451 	  if (unlikely (data + 4 > end_data))
452 	    goto invalid;
453 
454 	  newloc->number = read_4ubyte_unaligned_inc (&bo, data);
455 	  break;
456 
457 	case DW_OP_const4s:
458 	case DW_OP_call4:
459 	case DW_OP_GNU_parameter_ref:
460 	  if (unlikely (data + 4 > end_data))
461 	    goto invalid;
462 
463 	  newloc->number = read_4sbyte_unaligned_inc (&bo, data);
464 	  break;
465 
466 	case DW_OP_const8u:
467 	  if (unlikely (data + 8 > end_data))
468 	    goto invalid;
469 
470 	  newloc->number = read_8ubyte_unaligned_inc (&bo, data);
471 	  break;
472 
473 	case DW_OP_const8s:
474 	  if (unlikely (data + 8 > end_data))
475 	    goto invalid;
476 
477 	  newloc->number = read_8sbyte_unaligned_inc (&bo, data);
478 	  break;
479 
480 	case DW_OP_constu:
481 	case DW_OP_plus_uconst:
482 	case DW_OP_regx:
483 	case DW_OP_piece:
484 	case DW_OP_convert:
485 	case DW_OP_GNU_convert:
486 	case DW_OP_reinterpret:
487 	case DW_OP_GNU_reinterpret:
488 	case DW_OP_addrx:
489 	case DW_OP_GNU_addr_index:
490 	case DW_OP_constx:
491 	case DW_OP_GNU_const_index:
492 	  get_uleb128 (newloc->number, data, end_data);
493 	  break;
494 
495 	case DW_OP_consts:
496 	case DW_OP_breg0 ... DW_OP_breg31:
497 	case DW_OP_fbreg:
498 	  get_sleb128 (newloc->number, data, end_data);
499 	  break;
500 
501 	case DW_OP_bregx:
502 	  get_uleb128 (newloc->number, data, end_data);
503 	  if (unlikely (data >= end_data))
504 	    goto invalid;
505 	  get_sleb128 (newloc->number2, data, end_data);
506 	  break;
507 
508 	case DW_OP_bit_piece:
509 	case DW_OP_regval_type:
510 	case DW_OP_GNU_regval_type:
511 	  get_uleb128 (newloc->number, data, end_data);
512 	  if (unlikely (data >= end_data))
513 	    goto invalid;
514 	  get_uleb128 (newloc->number2, data, end_data);
515 	  break;
516 
517 	case DW_OP_implicit_value:
518 	case DW_OP_entry_value:
519 	case DW_OP_GNU_entry_value:
520 	  /* This cannot be used in a CFI expression.  */
521 	  if (unlikely (dbg == NULL))
522 	    goto invalid;
523 
524 	  /* start of block inc. len.  */
525 	  newloc->number2 = (Dwarf_Word) (uintptr_t) data;
526 	  get_uleb128 (newloc->number, data, end_data); /* Block length.  */
527 	  if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number))
528 	    goto invalid;
529 	  data += newloc->number;		/* Skip the block.  */
530 	  break;
531 
532 	case DW_OP_implicit_pointer:
533 	case DW_OP_GNU_implicit_pointer:
534 	  /* DW_FORM_ref_addr, depends on offset size of CU.  */
535 	  if (dbg == NULL || __libdw_read_offset_inc (dbg, sec_index, &data,
536 						      ref_size,
537 						      &newloc->number,
538 						      IDX_debug_info, 0))
539 	    goto invalid;
540 	  if (unlikely (data >= end_data))
541 	    goto invalid;
542 	  get_uleb128 (newloc->number2, data, end_data); /* Byte offset.  */
543 	  break;
544 
545 	case DW_OP_deref_type:
546 	case DW_OP_GNU_deref_type:
547 	case DW_OP_xderef_type:
548 	  if (unlikely (data + 1 >= end_data))
549 	    goto invalid;
550 	  newloc->number = *data++;
551 	  get_uleb128 (newloc->number2, data, end_data);
552 	  break;
553 
554 	case DW_OP_const_type:
555 	case DW_OP_GNU_const_type:
556 	  {
557 	    size_t size;
558 	    get_uleb128 (newloc->number, data, end_data);
559 	    if (unlikely (data >= end_data))
560 	      goto invalid;
561 
562 	    /* start of block inc. len.  */
563 	    newloc->number2 = (Dwarf_Word) (uintptr_t) data;
564 	    size = *data++;
565 	    if (unlikely ((Dwarf_Word) (end_data - data) < size))
566 	      goto invalid;
567 	    data += size;		/* Skip the block.  */
568 	  }
569 	  break;
570 
571 	default:
572 	  goto invalid;
573 	}
574     }
575 
576   if (unlikely (n == 0))
577     {
578       /* This is not allowed.
579 	 It would mean an empty location expression, which we handled
580 	 already as a special case above.  */
581       goto invalid;
582     }
583 
584   if (valuep)
585     {
586       struct loclist *newloc = NEW_LOC ();
587       newloc->atom = DW_OP_stack_value;
588       newloc->number = 0;
589       newloc->number2 = 0;
590       newloc->offset = data - block->data;
591     }
592 
593   /* Allocate the array.  */
594   Dwarf_Op *result;
595   if (dbg != NULL)
596     result = libdw_alloc (dbg, Dwarf_Op, sizeof (Dwarf_Op), n);
597   else
598     {
599       result = malloc (sizeof *result * n);
600       if (result == NULL)
601 	{
602 	nomem:
603 	  __libdw_seterrno (DWARF_E_NOMEM);
604 	  goto returnmem;
605 	}
606     }
607 
608   /* Store the result.  */
609   *llbuf = result;
610   *listlen = n;
611 
612   do
613     {
614       /* We populate the array from the back since the list is backwards.  */
615       --n;
616       result[n].atom = loclist->atom;
617       result[n].number = loclist->number;
618       result[n].number2 = loclist->number2;
619       result[n].offset = loclist->offset;
620 
621       if (result[n].atom == DW_OP_implicit_value)
622 	{
623 	  int store = store_implicit_value (dbg, cache, &result[n]);
624 	  if (unlikely (store != 0))
625 	    {
626 	      if (store < 0)
627 	        goto invalid;
628 	      else
629 		goto nomem;
630 	    }
631 	}
632 
633       struct loclist *loc = loclist;
634       loclist = loclist->next;
635       if (unlikely (n + 1 > MAX_STACK_LOCS))
636 	free (loc);
637     }
638   while (n > 0);
639 
640   /* Insert a record in the search tree so that we can find it again later.  */
641   struct loc_s *newp;
642   if (dbg != NULL)
643     newp = libdw_alloc (dbg, struct loc_s, sizeof (struct loc_s), 1);
644   else
645     {
646       newp = malloc (sizeof *newp);
647       if (newp == NULL)
648 	{
649 	  free (result);
650 	  goto nomem;
651 	}
652     }
653 
654   newp->addr = block->data;
655   newp->loc = result;
656   newp->nloc = *listlen;
657   (void) tsearch (newp, cache, loc_compare);
658 
659   /* We did it.  */
660   return 0;
661 }
662 
663 static int
getlocation(struct Dwarf_CU * cu,const Dwarf_Block * block,Dwarf_Op ** llbuf,size_t * listlen,int sec_index)664 getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
665 	     Dwarf_Op **llbuf, size_t *listlen, int sec_index)
666 {
667   /* Empty location expressions don't have any ops to intern.
668      Note that synthetic empty_cu doesn't have an associated DWARF dbg.  */
669   if (block->length == 0)
670     {
671       *listlen = 0;
672       return 0;
673     }
674 
675   return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order,
676 				    cu->address_size, (cu->version == 2
677 						       ? cu->address_size
678 						       : cu->offset_size),
679 				    &cu->locs, block,
680 				    false, false,
681 				    llbuf, listlen, sec_index);
682 }
683 
684 int
dwarf_getlocation(Dwarf_Attribute * attr,Dwarf_Op ** llbuf,size_t * listlen)685 dwarf_getlocation (Dwarf_Attribute *attr, Dwarf_Op **llbuf, size_t *listlen)
686 {
687   if (! attr_ok (attr))
688     return -1;
689 
690   int result = is_constant_offset (attr, llbuf, listlen);
691   if (result != 1)
692     return result; /* Either success 0, or -1 to indicate error.  */
693 
694   /* If it has a block form, it's a single location expression.
695      Except for DW_FORM_data16, which is a 128bit constant.  */
696   if (attr->form == DW_FORM_data16)
697     {
698       __libdw_seterrno (DWARF_E_NO_BLOCK);
699       return -1;
700     }
701   Dwarf_Block block;
702   if (INTUSE(dwarf_formblock) (attr, &block) != 0)
703     return -1;
704 
705   return getlocation (attr->cu, &block, llbuf, listlen, cu_sec_idx (attr->cu));
706 }
707 
708 Dwarf_Addr
__libdw_cu_base_address(Dwarf_CU * cu)709 __libdw_cu_base_address (Dwarf_CU *cu)
710 {
711   if (cu->base_address == (Dwarf_Addr) -1)
712     {
713       Dwarf_Addr base;
714 
715       /* Fetch the CU's base address.  */
716       Dwarf_Die cudie = CUDIE (cu);
717 
718       /* Find the base address of the compilation unit.  It will
719 	 normally be specified by DW_AT_low_pc.  In DWARF-3 draft 4,
720 	 the base address could be overridden by DW_AT_entry_pc.  It's
721 	 been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc
722 	 for compilation units with discontinuous ranges.  */
723       Dwarf_Attribute attr_mem;
724       if (INTUSE(dwarf_lowpc) (&cudie, &base) != 0
725 	  && INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (&cudie,
726 							 DW_AT_entry_pc,
727 							 &attr_mem),
728 				     &base) != 0)
729 	{
730 	  /* The compiler provided no base address when it should
731 	     have.  Buggy GCC does this when it used absolute
732 	     addresses in the location list and no DW_AT_ranges.  */
733 	   base = 0;
734 	}
735       cu->base_address = base;
736     }
737 
738   return cu->base_address;
739 }
740 
741 static int
initial_offset(Dwarf_Attribute * attr,ptrdiff_t * offset)742 initial_offset (Dwarf_Attribute *attr, ptrdiff_t *offset)
743 {
744   size_t secidx = (attr->cu->version < 5
745 		   ? IDX_debug_loc : IDX_debug_loclists);
746 
747   Dwarf_Word start_offset;
748   if (attr->form == DW_FORM_loclistx)
749     {
750       Dwarf_Word idx;
751       Dwarf_CU *cu = attr->cu;
752       const unsigned char *datap = attr->valp;
753       const unsigned char *endp = cu->endp;
754       if (datap >= endp)
755 	{
756 	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
757 	  return -1;
758 	}
759       get_uleb128 (idx, datap, endp);
760 
761       Elf_Data *data = cu->dbg->sectiondata[secidx];
762       if (data == NULL && cu->unit_type == DW_UT_split_compile)
763 	{
764 	  cu = __libdw_find_split_unit (cu);
765 	  if (cu != NULL)
766 	    data = cu->dbg->sectiondata[secidx];
767 	}
768 
769       if (data == NULL)
770 	{
771 	  __libdw_seterrno (secidx == IDX_debug_loc
772                             ? DWARF_E_NO_DEBUG_LOC
773                             : DWARF_E_NO_DEBUG_LOCLISTS);
774 	  return -1;
775 	}
776 
777       Dwarf_Off loc_base_off = __libdw_cu_locs_base (cu);
778 
779       /* The section should at least contain room for one offset.  */
780       size_t sec_size = cu->dbg->sectiondata[secidx]->d_size;
781       size_t offset_size = cu->offset_size;
782       if (offset_size > sec_size)
783 	{
784 	invalid_offset:
785 	  __libdw_seterrno (DWARF_E_INVALID_OFFSET);
786 	  return -1;
787 	}
788 
789       /* And the base offset should be at least inside the section.  */
790       if (loc_base_off > (sec_size - offset_size))
791 	goto invalid_offset;
792 
793       size_t max_idx = (sec_size - offset_size - loc_base_off) / offset_size;
794       if (idx > max_idx)
795 	goto invalid_offset;
796 
797       datap = (cu->dbg->sectiondata[secidx]->d_buf
798 	       + loc_base_off + (idx * offset_size));
799       if (offset_size == 4)
800 	start_offset = read_4ubyte_unaligned (cu->dbg, datap);
801       else
802 	start_offset = read_8ubyte_unaligned (cu->dbg, datap);
803 
804       start_offset += loc_base_off;
805     }
806   else
807     {
808       if (__libdw_formptr (attr, secidx,
809 			   (secidx == IDX_debug_loc
810 			    ? DWARF_E_NO_DEBUG_LOC
811 			    : DWARF_E_NO_DEBUG_LOCLISTS),
812 			    NULL, &start_offset) == NULL)
813 	return -1;
814     }
815 
816   *offset = start_offset;
817   return 0;
818 }
819 
820 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)821 getlocations_addr (Dwarf_Attribute *attr, ptrdiff_t offset,
822 		   Dwarf_Addr *basep, Dwarf_Addr *startp, Dwarf_Addr *endp,
823 		   Dwarf_Addr address, const Elf_Data *locs, Dwarf_Op **expr,
824 		   size_t *exprlen)
825 {
826   Dwarf_CU *cu = attr->cu;
827   Dwarf *dbg = cu->dbg;
828   size_t secidx = cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
829   const unsigned char *readp = locs->d_buf + offset;
830   const unsigned char *readendp = locs->d_buf + locs->d_size;
831 
832   Dwarf_Addr begin;
833   Dwarf_Addr end;
834 
835  next:
836   switch (__libdw_read_begin_end_pair_inc (cu, secidx,
837 					   &readp, readendp,
838 					   cu->address_size,
839 					   &begin, &end, basep))
840     {
841     case 0: /* got location range. */
842       break;
843     case 1: /* base address setup. */
844       goto next;
845     case 2: /* end of loclist */
846       return 0;
847     default: /* error */
848       return -1;
849     }
850 
851   /* We have a location expression.  */
852   Dwarf_Block block;
853   if (secidx == IDX_debug_loc)
854     {
855       if (readendp - readp < 2)
856 	{
857 	invalid:
858 	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
859 	  return -1;
860 	}
861       block.length = read_2ubyte_unaligned_inc (dbg, readp);
862     }
863   else
864     {
865       if (readendp - readp < 1)
866 	goto invalid;
867       get_uleb128 (block.length, readp, readendp);
868     }
869   block.data = (unsigned char *) readp;
870   if (readendp - readp < (ptrdiff_t) block.length)
871     goto invalid;
872   readp += block.length;
873 
874   /* Note these addresses include any base (if necessary) already.  */
875   *startp = begin;
876   *endp = end;
877 
878   /* If address is minus one we want them all, otherwise only matching.  */
879   if (address != (Dwarf_Word) -1 && (address < *startp || address >= *endp))
880     goto next;
881 
882   if (getlocation (cu, &block, expr, exprlen, secidx) != 0)
883     return -1;
884 
885   return readp - (unsigned char *) locs->d_buf;
886 }
887 
888 int
dwarf_getlocation_addr(Dwarf_Attribute * attr,Dwarf_Addr address,Dwarf_Op ** llbufs,size_t * listlens,size_t maxlocs)889 dwarf_getlocation_addr (Dwarf_Attribute *attr, Dwarf_Addr address,
890 			Dwarf_Op **llbufs, size_t *listlens, size_t maxlocs)
891 {
892   if (! attr_ok (attr))
893     return -1;
894 
895   if (llbufs == NULL)
896     maxlocs = SIZE_MAX;
897 
898   /* If it has a block form, it's a single location expression.
899      Except for DW_FORM_data16, which is a 128bit constant.  */
900   Dwarf_Block block;
901   if (attr->form != DW_FORM_data16
902       && INTUSE(dwarf_formblock) (attr, &block) == 0)
903     {
904       if (maxlocs == 0)
905 	return 0;
906       if (llbufs != NULL &&
907 	  getlocation (attr->cu, &block, &llbufs[0], &listlens[0],
908 		       cu_sec_idx (attr->cu)) != 0)
909 	return -1;
910       return listlens[0] == 0 ? 0 : 1;
911     }
912 
913   if (attr->form != DW_FORM_data16)
914     {
915       int error = INTUSE(dwarf_errno) ();
916       if (unlikely (error != DWARF_E_NO_BLOCK))
917 	{
918 	  __libdw_seterrno (error);
919 	  return -1;
920 	}
921     }
922 
923   /* If is_constant_offset is successful, we are done with 1 result.  */
924   int result = is_constant_offset (attr, llbufs, listlens);
925   if (result != 1)
926     return result ?: 1;
927 
928   Dwarf_Addr base, start, end;
929   Dwarf_Op *expr;
930   size_t expr_len;
931   ptrdiff_t off = 0;
932   size_t got = 0;
933 
934   /* This is a true loclistptr, fetch the initial base address and offset.  */
935   base = __libdw_cu_base_address (attr->cu);
936   if (base == (Dwarf_Addr) -1)
937     return -1;
938 
939   if (initial_offset (attr, &off) != 0)
940     return -1;
941 
942   size_t secidx = attr->cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
943   const Elf_Data *d = attr->cu->dbg->sectiondata[secidx];
944 
945   while (got < maxlocs
946          && (off = getlocations_addr (attr, off, &base, &start, &end,
947 				      address, d, &expr, &expr_len)) > 0)
948     {
949       /* This one matches the address.  */
950       if (llbufs != NULL)
951 	{
952 	  llbufs[got] = expr;
953 	  listlens[got] = expr_len;
954 	}
955       ++got;
956     }
957 
958   /* We might stop early, so off can be zero or positive on success.  */
959   if (off < 0)
960     return -1;
961 
962   return got;
963 }
964 
965 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)966 dwarf_getlocations (Dwarf_Attribute *attr, ptrdiff_t offset, Dwarf_Addr *basep,
967 		    Dwarf_Addr *startp, Dwarf_Addr *endp, Dwarf_Op **expr,
968 		    size_t *exprlen)
969 {
970   if (! attr_ok (attr))
971     return -1;
972 
973   /* 1 is an invalid offset, meaning no more locations. */
974   if (offset == 1)
975     return 0;
976 
977   if (offset == 0)
978     {
979       /* If it has a block form, it's a single location expression.
980 	 Except for DW_FORM_data16, which is a 128bit constant.  */
981       Dwarf_Block block;
982       if (attr->form != DW_FORM_data16
983 	  && INTUSE(dwarf_formblock) (attr, &block) == 0)
984 	{
985 	  if (getlocation (attr->cu, &block, expr, exprlen,
986 			   cu_sec_idx (attr->cu)) != 0)
987 	    return -1;
988 
989 	  /* This is the one and only location covering everything. */
990 	  *startp = 0;
991 	  *endp = -1;
992 	  return 1;
993 	}
994 
995       if (attr->form != DW_FORM_data16)
996 	{
997 	  int error = INTUSE(dwarf_errno) ();
998 	  if (unlikely (error != DWARF_E_NO_BLOCK))
999 	    {
1000 	      __libdw_seterrno (error);
1001 	      return -1;
1002 	    }
1003 	}
1004 
1005       int result = is_constant_offset (attr, expr, exprlen);
1006       if (result != 1)
1007 	{
1008 	  if (result == 0)
1009 	    {
1010 	      /* This is the one and only location covering everything. */
1011 	      *startp = 0;
1012 	      *endp = -1;
1013 	      return 1;
1014 	    }
1015 	  return result; /* Something bad, dwarf_errno has been set.  */
1016 	}
1017 
1018       /* We must be looking at a true loclistptr, fetch the initial
1019 	 base address and offset.  */
1020       *basep = __libdw_cu_base_address (attr->cu);
1021       if (*basep == (Dwarf_Addr) -1)
1022 	return -1;
1023 
1024       if (initial_offset (attr, &offset) != 0)
1025 	return -1;
1026     }
1027 
1028   size_t secidx = attr->cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
1029   const Elf_Data *d = attr->cu->dbg->sectiondata[secidx];
1030 
1031   return getlocations_addr (attr, offset, basep, startp, endp,
1032 			    (Dwarf_Word) -1, d, expr, exprlen);
1033 }
1034