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