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