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