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