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