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