resetting manifest requested domain to floor
[platform/upstream/elfutils.git] / libdw / dwarf_getlocation.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }