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