1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Return location expression list.
25316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard   Copyright (C) 2000-2010, 2013-2015 Red Hat, Inc.
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is part of elfutils.
4b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
5b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is free software; you can redistribute it and/or modify
7de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   it under the terms of either
8b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU Lesser General Public License as published by the Free
10de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 3 of the License, or (at
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
12de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU General Public License as published by the Free
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 2 of the License, or (at
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
18de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
19de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or both in parallel, as here.
20de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
21de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   elfutils is distributed in the hope that it will be useful, but
22361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   WITHOUT ANY WARRANTY; without even the implied warranty of
23361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   General Public License for more details.
25361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper
26de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   You should have received copies of the GNU General Public License and
27de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   the GNU Lesser General Public License along with this program.  If
28de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   not, see <http://www.gnu.org/licenses/>.  */
29b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
30b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#ifdef HAVE_CONFIG_H
31b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper# include <config.h>
32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
33b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
34b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <dwarf.h>
35b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <search.h>
36b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdlib.h>
37cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath#include <assert.h>
38b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
39b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <libdwP.h>
40b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
41b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
42b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool
43b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperattr_ok (Dwarf_Attribute *attr)
44b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
45b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (attr == NULL)
46b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return false;
47b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
48b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Must be one of the attributes listed below.  */
49b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (attr->code)
50b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
51b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case DW_AT_location:
52b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case DW_AT_data_member_location:
53b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case DW_AT_vtable_elem_location:
54b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case DW_AT_string_length:
55b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case DW_AT_use_location:
56b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case DW_AT_frame_base:
57b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case DW_AT_return_addr:
58b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case DW_AT_static_link:
5966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    case DW_AT_segment:
60476feb1c7db2c6dfa217f8a18d2eb1af2789cbb0Petr Machata    case DW_AT_GNU_call_site_value:
61476feb1c7db2c6dfa217f8a18d2eb1af2789cbb0Petr Machata    case DW_AT_GNU_call_site_data_value:
62476feb1c7db2c6dfa217f8a18d2eb1af2789cbb0Petr Machata    case DW_AT_GNU_call_site_target:
63476feb1c7db2c6dfa217f8a18d2eb1af2789cbb0Petr Machata    case DW_AT_GNU_call_site_target_clobbered:
64b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
65b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
66b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
67b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      __libdw_seterrno (DWARF_E_NO_LOCLIST);
68b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return false;
69b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
70b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
71b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return true;
72b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
73b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
74b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
75b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstruct loclist
76b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
77b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  uint8_t atom;
78b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Dwarf_Word number;
79b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Dwarf_Word number2;
80b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Dwarf_Word offset;
81b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct loclist *next;
82b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
83b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
84b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
85b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int
86b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperloc_compare (const void *p1, const void *p2)
87b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
88b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const struct loc_s *l1 = (const struct loc_s *) p1;
89b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const struct loc_s *l2 = (const struct loc_s *) p2;
90b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
91b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((uintptr_t) l1->addr < (uintptr_t) l2->addr)
92b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return -1;
93b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((uintptr_t) l1->addr > (uintptr_t) l2->addr)
94b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return 1;
95b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
96b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 0;
97b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
98b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
99f0371041995308d197447019eb2ac9285c96477bRoland McGrath/* For each DW_OP_implicit_value, we store a special entry in the cache.
100f0371041995308d197447019eb2ac9285c96477bRoland McGrath   This points us directly to the block data for later fetching.  */
101f0371041995308d197447019eb2ac9285c96477bRoland McGrathstatic void
102b2535b6a6be7717cdd41834d76e5cb48cb446b83Mark Wielaardstore_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op)
103f0371041995308d197447019eb2ac9285c96477bRoland McGrath{
104f0371041995308d197447019eb2ac9285c96477bRoland McGrath  struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s,
105f0371041995308d197447019eb2ac9285c96477bRoland McGrath					   sizeof (struct loc_block_s), 1);
10674f9b7337562c06a93722ad757d258db8f082663Mark Wielaard  const unsigned char *data = (const unsigned char *) (uintptr_t) op->number2;
1077a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard  // Ignored, equal to op->number.  And data length already checked.
1087a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard  (void) __libdw_get_uleb128 (&data, data + len_leb128 (Dwarf_Word));
109f0371041995308d197447019eb2ac9285c96477bRoland McGrath  block->addr = op;
110b2535b6a6be7717cdd41834d76e5cb48cb446b83Mark Wielaard  block->data = (unsigned char *) data;
111f0371041995308d197447019eb2ac9285c96477bRoland McGrath  block->length = op->number;
112f0371041995308d197447019eb2ac9285c96477bRoland McGrath  (void) tsearch (block, cache, loc_compare);
113f0371041995308d197447019eb2ac9285c96477bRoland McGrath}
114f0371041995308d197447019eb2ac9285c96477bRoland McGrath
115f0371041995308d197447019eb2ac9285c96477bRoland McGrathint
1161ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaarddwarf_getlocation_implicit_value (Dwarf_Attribute *attr, const Dwarf_Op *op,
1171ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaard				  Dwarf_Block *return_block)
118f0371041995308d197447019eb2ac9285c96477bRoland McGrath{
119f0371041995308d197447019eb2ac9285c96477bRoland McGrath  if (attr == NULL)
120f0371041995308d197447019eb2ac9285c96477bRoland McGrath    return -1;
121f0371041995308d197447019eb2ac9285c96477bRoland McGrath
1227e0aecdad525d8b290e2b9b999f6960a42bee33dRoland McGrath  struct loc_block_s fake = { .addr = (void *) op };
123f0371041995308d197447019eb2ac9285c96477bRoland McGrath  struct loc_block_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
124f0371041995308d197447019eb2ac9285c96477bRoland McGrath  if (unlikely (found == NULL))
125f0371041995308d197447019eb2ac9285c96477bRoland McGrath    {
126f0371041995308d197447019eb2ac9285c96477bRoland McGrath      __libdw_seterrno (DWARF_E_NO_BLOCK);
127f0371041995308d197447019eb2ac9285c96477bRoland McGrath      return -1;
128f0371041995308d197447019eb2ac9285c96477bRoland McGrath    }
129f0371041995308d197447019eb2ac9285c96477bRoland McGrath
130f0371041995308d197447019eb2ac9285c96477bRoland McGrath  return_block->length = (*found)->length;
131f0371041995308d197447019eb2ac9285c96477bRoland McGrath  return_block->data = (*found)->data;
132f0371041995308d197447019eb2ac9285c96477bRoland McGrath  return 0;
133f0371041995308d197447019eb2ac9285c96477bRoland McGrath}
134f0371041995308d197447019eb2ac9285c96477bRoland McGrath
135cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath/* DW_AT_data_member_location can be a constant as well as a loclistptr.
136cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath   Only data[48] indicate a loclistptr.  */
137cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrathstatic int
138cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrathcheck_constant_offset (Dwarf_Attribute *attr,
139cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath		       Dwarf_Op **llbuf, size_t *listlen)
140cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath{
141888381b9ace5251b9feaad14f9bfa8c9d85cb1fdRoland McGrath  if (attr->code != DW_AT_data_member_location)
142cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath    return 1;
143cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath
144888381b9ace5251b9feaad14f9bfa8c9d85cb1fdRoland McGrath  switch (attr->form)
145888381b9ace5251b9feaad14f9bfa8c9d85cb1fdRoland McGrath    {
146888381b9ace5251b9feaad14f9bfa8c9d85cb1fdRoland McGrath      /* Punt for any non-constant form.  */
147888381b9ace5251b9feaad14f9bfa8c9d85cb1fdRoland McGrath    default:
148888381b9ace5251b9feaad14f9bfa8c9d85cb1fdRoland McGrath      return 1;
149888381b9ace5251b9feaad14f9bfa8c9d85cb1fdRoland McGrath
150888381b9ace5251b9feaad14f9bfa8c9d85cb1fdRoland McGrath    case DW_FORM_data1:
151888381b9ace5251b9feaad14f9bfa8c9d85cb1fdRoland McGrath    case DW_FORM_data2:
152c16966a0043dc173fcaab5d3f8b754b4e9c9ceb7Roland McGrath    case DW_FORM_data4:
153c16966a0043dc173fcaab5d3f8b754b4e9c9ceb7Roland McGrath    case DW_FORM_data8:
154888381b9ace5251b9feaad14f9bfa8c9d85cb1fdRoland McGrath    case DW_FORM_sdata:
155888381b9ace5251b9feaad14f9bfa8c9d85cb1fdRoland McGrath    case DW_FORM_udata:
156888381b9ace5251b9feaad14f9bfa8c9d85cb1fdRoland McGrath      break;
157888381b9ace5251b9feaad14f9bfa8c9d85cb1fdRoland McGrath    }
158888381b9ace5251b9feaad14f9bfa8c9d85cb1fdRoland McGrath
159cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath  /* Check whether we already cached this location.  */
160cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath  struct loc_s fake = { .addr = attr->valp };
161cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath  struct loc_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
162cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath
163cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath  if (found == NULL)
164cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath    {
165cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath      Dwarf_Word offset;
166cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath      if (INTUSE(dwarf_formudata) (attr, &offset) != 0)
167cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath	return -1;
168cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath
169cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath      Dwarf_Op *result = libdw_alloc (attr->cu->dbg,
170cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath				      Dwarf_Op, sizeof (Dwarf_Op), 1);
171cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath
172cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath      result->atom = DW_OP_plus_uconst;
173cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath      result->number = offset;
174cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath      result->number2 = 0;
175cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath      result->offset = 0;
176cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath
177cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath      /* Insert a record in the search tree so we can find it again later.  */
178cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath      struct loc_s *newp = libdw_alloc (attr->cu->dbg,
179cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath					struct loc_s, sizeof (struct loc_s),
180cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath					1);
181cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath      newp->addr = attr->valp;
182cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath      newp->loc = result;
183cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath      newp->nloc = 1;
184cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath
185cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath      found = tsearch (newp, &attr->cu->locs, loc_compare);
186cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath    }
187cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath
188cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath  assert ((*found)->nloc == 1);
189cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath
190cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath  if (llbuf != NULL)
191cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath    {
192cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath      *llbuf = (*found)->loc;
193cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath      *listlen = 1;
194cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath    }
195cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath
196cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath  return 0;
197cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath}
198cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath
1993c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrathint
2003c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrathinternal_function
201688f7fcdb395cefef6a098b5ac9ddd167bb5fc3dRoland McGrath__libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
202688f7fcdb395cefef6a098b5ac9ddd167bb5fc3dRoland McGrath			   unsigned int address_size, unsigned int ref_size,
2030ab97839da3c382ab8799ebdbf5eb0a79bf20bdcRoland McGrath			   void **cache, const Dwarf_Block *block,
2040ab97839da3c382ab8799ebdbf5eb0a79bf20bdcRoland McGrath			   bool cfap, bool valuep,
2053c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath			   Dwarf_Op **llbuf, size_t *listlen, int sec_index)
206b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2073951f2ec0aaca021c77a2c7a464dcf43433261c3Mark Wielaard  /* Empty location expressions don't have any ops to intern.  */
2083951f2ec0aaca021c77a2c7a464dcf43433261c3Mark Wielaard  if (block->length == 0)
2093951f2ec0aaca021c77a2c7a464dcf43433261c3Mark Wielaard    {
2103951f2ec0aaca021c77a2c7a464dcf43433261c3Mark Wielaard      *listlen = 0;
2113951f2ec0aaca021c77a2c7a464dcf43433261c3Mark Wielaard      return 0;
2123951f2ec0aaca021c77a2c7a464dcf43433261c3Mark Wielaard    }
2133951f2ec0aaca021c77a2c7a464dcf43433261c3Mark Wielaard
214b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check whether we already looked at this list.  */
215b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct loc_s fake = { .addr = block->data };
2163c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  struct loc_s **found = tfind (&fake, cache, loc_compare);
217b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (found != NULL)
218b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
219b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We already saw it.  */
220b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      *llbuf = (*found)->loc;
221b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      *listlen = (*found)->nloc;
222b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
223af80014e49796185298dfb261ddf1e51d98f25c0Roland McGrath      if (valuep)
224af80014e49796185298dfb261ddf1e51d98f25c0Roland McGrath	{
225af80014e49796185298dfb261ddf1e51d98f25c0Roland McGrath	  assert (*listlen > 1);
226af80014e49796185298dfb261ddf1e51d98f25c0Roland McGrath	  assert ((*llbuf)[*listlen - 1].atom == DW_OP_stack_value);
227af80014e49796185298dfb261ddf1e51d98f25c0Roland McGrath	}
228af80014e49796185298dfb261ddf1e51d98f25c0Roland McGrath
229b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return 0;
230b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
231b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const unsigned char *data = block->data;
233b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const unsigned char *const end_data = data + block->length;
234b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2353c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  const struct { bool other_byte_order; } bo = { other_byte_order };
2363c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct loclist *loclist = NULL;
238b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  unsigned int n = 0;
23996a9fc6ae246e2e03f9d82f136960691fa4a88feJan Kratochvil
240720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard  /* Stack allocate at most this many locs.  */
241720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard#define MAX_STACK_LOCS 256
242720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard  struct loclist stack_locs[MAX_STACK_LOCS];
243720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard#define NEW_LOC() ({ struct loclist *ll;			\
244720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard		     ll = (likely (n < MAX_STACK_LOCS)		\
245720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard			   ? &stack_locs[n]			\
246720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard			   : malloc (sizeof (struct loclist)));	\
247720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard		     if (unlikely (ll == NULL))			\
248720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard		       goto nomem;				\
249720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard		     n++;					\
250720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard		     ll->next = loclist;			\
251720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard		     loclist = ll;				\
252720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard		     ll; })
253720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard
25496a9fc6ae246e2e03f9d82f136960691fa4a88feJan Kratochvil  if (cfap)
25596a9fc6ae246e2e03f9d82f136960691fa4a88feJan Kratochvil    {
25696a9fc6ae246e2e03f9d82f136960691fa4a88feJan Kratochvil      /* Synthesize the operation to push the CFA before the expression.  */
257720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard      struct loclist *newloc = NEW_LOC ();
25896a9fc6ae246e2e03f9d82f136960691fa4a88feJan Kratochvil      newloc->atom = DW_OP_call_frame_cfa;
25996a9fc6ae246e2e03f9d82f136960691fa4a88feJan Kratochvil      newloc->number = 0;
26096a9fc6ae246e2e03f9d82f136960691fa4a88feJan Kratochvil      newloc->number2 = 0;
26196a9fc6ae246e2e03f9d82f136960691fa4a88feJan Kratochvil      newloc->offset = -1;
26296a9fc6ae246e2e03f9d82f136960691fa4a88feJan Kratochvil    }
26396a9fc6ae246e2e03f9d82f136960691fa4a88feJan Kratochvil
264b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Decode the opcodes.  It is possible in some situations to have a
265b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     block of size zero.  */
266b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while (data < end_data)
267b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
268b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      struct loclist *newloc;
269720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard      newloc = NEW_LOC ();
270b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      newloc->number = 0;
271b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      newloc->number2 = 0;
272b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      newloc->offset = data - block->data;
273b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
274b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      switch ((newloc->atom = *data++))
275b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
276b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_addr:
277b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Address, depends on address size of CU.  */
2785316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard	  if (dbg == NULL)
2795316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard	    {
2805316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard	      // XXX relocation?
2815316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard	      if (address_size == 4)
2825316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard		{
2835316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard		  if (unlikely (data + 4 > end_data))
2845316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard		    goto invalid;
2855316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard		  else
2865316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard		    newloc->number = read_4ubyte_unaligned_inc (&bo, data);
2875316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard		}
2885316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard	      else
2895316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard		{
2905316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard		  if (unlikely (data + 8 > end_data))
2915316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard		    goto invalid;
2925316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard		  else
2935316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard		    newloc->number = read_8ubyte_unaligned_inc (&bo, data);
2945316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard		}
2955316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard	    }
2965316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard	  else if (__libdw_read_address_inc (dbg, sec_index, &data,
2975316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard					     address_size, &newloc->number))
2985316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard	    goto invalid;
299b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
300b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
301688f7fcdb395cefef6a098b5ac9ddd167bb5fc3dRoland McGrath	case DW_OP_call_ref:
302688f7fcdb395cefef6a098b5ac9ddd167bb5fc3dRoland McGrath	  /* DW_FORM_ref_addr, depends on offset size of CU.  */
3035316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard	  if (dbg == NULL || __libdw_read_offset_inc (dbg, sec_index, &data,
3045316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard						      ref_size,
3055316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard						      &newloc->number,
3065316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard						      IDX_debug_info, 0))
3075316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard	    goto invalid;
308688f7fcdb395cefef6a098b5ac9ddd167bb5fc3dRoland McGrath	  break;
309688f7fcdb395cefef6a098b5ac9ddd167bb5fc3dRoland McGrath
310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_deref:
311b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_dup:
312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_drop:
313b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_over:
314b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_swap:
315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_rot:
316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_xderef:
317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_abs:
318b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_and:
319b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_div:
320b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_minus:
321b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_mod:
322b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_mul:
323b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_neg:
324b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_not:
325b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_or:
326b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_plus:
327b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_shl:
328b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_shr:
329b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_shra:
330b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_xor:
331b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_eq:
332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_ge:
333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_gt:
334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_le:
335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_lt:
336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_ne:
337b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_lit0 ... DW_OP_lit31:
338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_reg0 ... DW_OP_reg31:
339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_nop:
340b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_push_object_address:
3418089343cc61743db7bf0fd75c21132cbab5c01fdRoland McGrath	case DW_OP_call_frame_cfa:
3427dd9464d06c7826952be3c4fa7fc963dd563c025Roland McGrath	case DW_OP_form_tls_address:
343d1083043cf63551270f31aa83233d55286a89d65Roland McGrath	case DW_OP_GNU_push_tls_address:
34496349ffaa68a1b4eec2fd1c9eb97a3d0b4e95a1eRoland McGrath	case DW_OP_stack_value:
345b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* No operand.  */
346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
347b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
348b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_const1u:
349b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_pick:
350b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_deref_size:
351b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_xderef_size:
352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (unlikely (data >= end_data))
35399d2372b25d1231d786b70278478c7a112f2b27cUlrich Drepper	    {
35499d2372b25d1231d786b70278478c7a112f2b27cUlrich Drepper	    invalid:
35599d2372b25d1231d786b70278478c7a112f2b27cUlrich Drepper	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
356720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard	    returnmem:
357720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard	      /* Free any dynamicly allocated loclists, if any.  */
358720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard	      while (n > MAX_STACK_LOCS)
359720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard		{
360720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard		  struct loclist *loc = loclist;
361720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard		  loclist = loc->next;
362720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard		  free (loc);
363720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard		  n--;
364720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard		}
36599d2372b25d1231d786b70278478c7a112f2b27cUlrich Drepper	      return -1;
36699d2372b25d1231d786b70278478c7a112f2b27cUlrich Drepper	    }
367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  newloc->number = *data++;
369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_const1s:
372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (unlikely (data >= end_data))
373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    goto invalid;
374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  newloc->number = *((int8_t *) data);
376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ++data;
377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
378b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
379b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_const2u:
380b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (unlikely (data + 2 > end_data))
381b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    goto invalid;
382b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3833c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  newloc->number = read_2ubyte_unaligned_inc (&bo, data);
384b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
385b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
386b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_const2s:
387b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_skip:
388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_bra:
389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_call2:
390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (unlikely (data + 2 > end_data))
391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    goto invalid;
392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3933c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  newloc->number = read_2sbyte_unaligned_inc (&bo, data);
394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_const4u:
397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (unlikely (data + 4 > end_data))
398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    goto invalid;
399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4003c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  newloc->number = read_4ubyte_unaligned_inc (&bo, data);
401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_const4s:
404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_call4:
405b5c0b037203eea0dc41f93900330522fe821eca9Petr Machata	case DW_OP_GNU_parameter_ref:
406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (unlikely (data + 4 > end_data))
407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    goto invalid;
408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4093c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  newloc->number = read_4sbyte_unaligned_inc (&bo, data);
410b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
411b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_const8u:
413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (unlikely (data + 8 > end_data))
414b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    goto invalid;
415b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4163c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  newloc->number = read_8ubyte_unaligned_inc (&bo, data);
417b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
418b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
419b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_const8s:
420b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (unlikely (data + 8 > end_data))
421b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    goto invalid;
422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4233c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  newloc->number = read_8sbyte_unaligned_inc (&bo, data);
424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_constu:
427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_plus_uconst:
428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_regx:
429b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_piece:
430b5c0b037203eea0dc41f93900330522fe821eca9Petr Machata	case DW_OP_GNU_convert:
431b5c0b037203eea0dc41f93900330522fe821eca9Petr Machata	case DW_OP_GNU_reinterpret:
4327a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (newloc->number, data, end_data);
433b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
435b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_consts:
436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_breg0 ... DW_OP_breg31:
437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_fbreg:
4387a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_sleb128 (newloc->number, data, end_data);
439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
440b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
441b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case DW_OP_bregx:
4427a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (newloc->number, data, end_data);
4437a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  if (unlikely (data >= end_data))
4447a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	    goto invalid;
4457a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_sleb128 (newloc->number2, data, end_data);
446b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
447b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4487dd9464d06c7826952be3c4fa7fc963dd563c025Roland McGrath	case DW_OP_bit_piece:
449b5c0b037203eea0dc41f93900330522fe821eca9Petr Machata	case DW_OP_GNU_regval_type:
4507a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (newloc->number, data, end_data);
4517a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  if (unlikely (data >= end_data))
4527a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	    goto invalid;
4537a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (newloc->number2, data, end_data);
4547dd9464d06c7826952be3c4fa7fc963dd563c025Roland McGrath	  break;
4557dd9464d06c7826952be3c4fa7fc963dd563c025Roland McGrath
456f0371041995308d197447019eb2ac9285c96477bRoland McGrath	case DW_OP_implicit_value:
457b5c0b037203eea0dc41f93900330522fe821eca9Petr Machata	case DW_OP_GNU_entry_value:
458f0371041995308d197447019eb2ac9285c96477bRoland McGrath	  /* This cannot be used in a CFI expression.  */
459f0371041995308d197447019eb2ac9285c96477bRoland McGrath	  if (unlikely (dbg == NULL))
460f0371041995308d197447019eb2ac9285c96477bRoland McGrath	    goto invalid;
461f0371041995308d197447019eb2ac9285c96477bRoland McGrath
46274f9b7337562c06a93722ad757d258db8f082663Mark Wielaard	  /* start of block inc. len.  */
46374f9b7337562c06a93722ad757d258db8f082663Mark Wielaard	  newloc->number2 = (Dwarf_Word) (uintptr_t) data;
4647a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (newloc->number, data, end_data); /* Block length.  */
465f0371041995308d197447019eb2ac9285c96477bRoland McGrath	  if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number))
466f0371041995308d197447019eb2ac9285c96477bRoland McGrath	    goto invalid;
467f0371041995308d197447019eb2ac9285c96477bRoland McGrath	  data += newloc->number;		/* Skip the block.  */
468f0371041995308d197447019eb2ac9285c96477bRoland McGrath	  break;
469f0371041995308d197447019eb2ac9285c96477bRoland McGrath
470932585d2385c9d4e5686e4ddc9ba30c68172d7f3Roland McGrath	case DW_OP_GNU_implicit_pointer:
471932585d2385c9d4e5686e4ddc9ba30c68172d7f3Roland McGrath	  /* DW_FORM_ref_addr, depends on offset size of CU.  */
4725316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard	  if (dbg == NULL || __libdw_read_offset_inc (dbg, sec_index, &data,
4735316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard						      ref_size,
4745316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard						      &newloc->number,
4755316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard						      IDX_debug_info, 0))
4765316e412a4931d99ac5611e5f89ef187d4e9e335Mark Wielaard	    goto invalid;
4777a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  if (unlikely (data >= end_data))
4787a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	    goto invalid;
4797a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (newloc->number2, data, end_data); /* Byte offset.  */
480932585d2385c9d4e5686e4ddc9ba30c68172d7f3Roland McGrath	  break;
481932585d2385c9d4e5686e4ddc9ba30c68172d7f3Roland McGrath
482b5c0b037203eea0dc41f93900330522fe821eca9Petr Machata	case DW_OP_GNU_deref_type:
4837a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  if (unlikely (data + 1 >= end_data))
484b5c0b037203eea0dc41f93900330522fe821eca9Petr Machata	    goto invalid;
485b5c0b037203eea0dc41f93900330522fe821eca9Petr Machata	  newloc->number = *data++;
4867a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (newloc->number2, data, end_data);
487b5c0b037203eea0dc41f93900330522fe821eca9Petr Machata	  break;
488b5c0b037203eea0dc41f93900330522fe821eca9Petr Machata
489b5c0b037203eea0dc41f93900330522fe821eca9Petr Machata	case DW_OP_GNU_const_type:
490b2535b6a6be7717cdd41834d76e5cb48cb446b83Mark Wielaard	  {
491b2535b6a6be7717cdd41834d76e5cb48cb446b83Mark Wielaard	    size_t size;
4927a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	    get_uleb128 (newloc->number, data, end_data);
493b2535b6a6be7717cdd41834d76e5cb48cb446b83Mark Wielaard	    if (unlikely (data >= end_data))
494b2535b6a6be7717cdd41834d76e5cb48cb446b83Mark Wielaard	      goto invalid;
495b2535b6a6be7717cdd41834d76e5cb48cb446b83Mark Wielaard
49674f9b7337562c06a93722ad757d258db8f082663Mark Wielaard	    /* start of block inc. len.  */
49774f9b7337562c06a93722ad757d258db8f082663Mark Wielaard	    newloc->number2 = (Dwarf_Word) (uintptr_t) data;
498b2535b6a6be7717cdd41834d76e5cb48cb446b83Mark Wielaard	    size = *data++;
499b2535b6a6be7717cdd41834d76e5cb48cb446b83Mark Wielaard	    if (unlikely ((Dwarf_Word) (end_data - data) < size))
500b2535b6a6be7717cdd41834d76e5cb48cb446b83Mark Wielaard	      goto invalid;
501b2535b6a6be7717cdd41834d76e5cb48cb446b83Mark Wielaard	    data += size;		/* Skip the block.  */
502b2535b6a6be7717cdd41834d76e5cb48cb446b83Mark Wielaard	  }
503b5c0b037203eea0dc41f93900330522fe821eca9Petr Machata	  break;
504b5c0b037203eea0dc41f93900330522fe821eca9Petr Machata
505b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	default:
506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  goto invalid;
507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
508b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
510b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (unlikely (n == 0))
511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
512b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* This is not allowed.
5133951f2ec0aaca021c77a2c7a464dcf43433261c3Mark Wielaard	 It would mean an empty location expression, which we handled
5143951f2ec0aaca021c77a2c7a464dcf43433261c3Mark Wielaard	 already as a special case above.  */
515b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      goto invalid;
516b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
517b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
518af80014e49796185298dfb261ddf1e51d98f25c0Roland McGrath  if (valuep)
519af80014e49796185298dfb261ddf1e51d98f25c0Roland McGrath    {
520720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard      struct loclist *newloc = NEW_LOC ();
521af80014e49796185298dfb261ddf1e51d98f25c0Roland McGrath      newloc->atom = DW_OP_stack_value;
522af80014e49796185298dfb261ddf1e51d98f25c0Roland McGrath      newloc->number = 0;
523af80014e49796185298dfb261ddf1e51d98f25c0Roland McGrath      newloc->number2 = 0;
524af80014e49796185298dfb261ddf1e51d98f25c0Roland McGrath      newloc->offset = data - block->data;
525af80014e49796185298dfb261ddf1e51d98f25c0Roland McGrath    }
526af80014e49796185298dfb261ddf1e51d98f25c0Roland McGrath
527b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Allocate the array.  */
5283c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  Dwarf_Op *result;
5293c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  if (dbg != NULL)
5303c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    result = libdw_alloc (dbg, Dwarf_Op, sizeof (Dwarf_Op), n);
5313c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  else
5323c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    {
5333c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      result = malloc (sizeof *result * n);
5343c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      if (result == NULL)
5353c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	{
5363c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	nomem:
5373c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  __libdw_seterrno (DWARF_E_NOMEM);
538720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard	  goto returnmem;
5393c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	}
5403c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    }
541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
542b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Store the result.  */
543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  *llbuf = result;
544b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  *listlen = n;
545b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
546b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  do
547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
548f0371041995308d197447019eb2ac9285c96477bRoland McGrath      /* We populate the array from the back since the list is backwards.  */
549b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      --n;
550b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result[n].atom = loclist->atom;
551b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result[n].number = loclist->number;
552b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result[n].number2 = loclist->number2;
553b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result[n].offset = loclist->offset;
554b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
555f0371041995308d197447019eb2ac9285c96477bRoland McGrath      if (result[n].atom == DW_OP_implicit_value)
556b2535b6a6be7717cdd41834d76e5cb48cb446b83Mark Wielaard	store_implicit_value (dbg, cache, &result[n]);
557f0371041995308d197447019eb2ac9285c96477bRoland McGrath
558720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard      struct loclist *loc = loclist;
559b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      loclist = loclist->next;
560720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard      if (unlikely (n + 1 > MAX_STACK_LOCS))
561720f83a563fd3d550cdc7a14be9fb13269022b91Mark Wielaard	free (loc);
562b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while (n > 0);
564b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
565f0371041995308d197447019eb2ac9285c96477bRoland McGrath  /* Insert a record in the search tree so that we can find it again later.  */
5663c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  struct loc_s *newp;
5673c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  if (dbg != NULL)
5683c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    newp = libdw_alloc (dbg, struct loc_s, sizeof (struct loc_s), 1);
5693c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  else
5703c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    {
5713c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      newp = malloc (sizeof *newp);
5723c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      if (newp == NULL)
5733c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	{
5743c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  free (result);
5753c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  goto nomem;
5763c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	}
5773c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    }
5783c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newp->addr = block->data;
580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newp->loc = result;
581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newp->nloc = *listlen;
5823c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  (void) tsearch (newp, cache, loc_compare);
583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We did it.  */
585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 0;
586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
5883c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrathstatic int
5893c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrathgetlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
5903c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	     Dwarf_Op **llbuf, size_t *listlen, int sec_index)
5913c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath{
5929202665816763fad8524dd78a664dbcaa157b8d4Mark Wielaard  /* Empty location expressions don't have any ops to intern.
5939202665816763fad8524dd78a664dbcaa157b8d4Mark Wielaard     Note that synthetic empty_cu doesn't have an associated DWARF dbg.  */
5949202665816763fad8524dd78a664dbcaa157b8d4Mark Wielaard  if (block->length == 0)
5959202665816763fad8524dd78a664dbcaa157b8d4Mark Wielaard    {
5969202665816763fad8524dd78a664dbcaa157b8d4Mark Wielaard      *listlen = 0;
5979202665816763fad8524dd78a664dbcaa157b8d4Mark Wielaard      return 0;
5989202665816763fad8524dd78a664dbcaa157b8d4Mark Wielaard    }
5999202665816763fad8524dd78a664dbcaa157b8d4Mark Wielaard
6003c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order,
601688f7fcdb395cefef6a098b5ac9ddd167bb5fc3dRoland McGrath				    cu->address_size, (cu->version == 2
602688f7fcdb395cefef6a098b5ac9ddd167bb5fc3dRoland McGrath						       ? cu->address_size
603688f7fcdb395cefef6a098b5ac9ddd167bb5fc3dRoland McGrath						       : cu->offset_size),
604688f7fcdb395cefef6a098b5ac9ddd167bb5fc3dRoland McGrath				    &cu->locs, block,
6050ab97839da3c382ab8799ebdbf5eb0a79bf20bdcRoland McGrath				    false, false,
606af80014e49796185298dfb261ddf1e51d98f25c0Roland McGrath				    llbuf, listlen, sec_index);
6073c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath}
6083c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
609b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperint
6101ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaarddwarf_getlocation (Dwarf_Attribute *attr, Dwarf_Op **llbuf, size_t *listlen)
611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
6126fb3451de3ba29b628be6e30a01ef104156d4733Ulrich Drepper  if (! attr_ok (attr))
6136fb3451de3ba29b628be6e30a01ef104156d4733Ulrich Drepper    return -1;
6146fb3451de3ba29b628be6e30a01ef104156d4733Ulrich Drepper
615cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath  int result = check_constant_offset (attr, llbuf, listlen);
616cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath  if (result != 1)
617cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath    return result;
618cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath
619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If it has a block form, it's a single location expression.  */
620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Dwarf_Block block;
621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (INTUSE(dwarf_formblock) (attr, &block) != 0)
622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return -1;
623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
6243e0f7d1d1b817040cef82f41879f471ab59b663eRoland McGrath  return getlocation (attr->cu, &block, llbuf, listlen, cu_sec_idx (attr->cu));
625b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
626b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
62766eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaardstatic int
6281ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaardattr_base_address (Dwarf_Attribute *attr, Dwarf_Addr *basep)
62966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard{
63066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  /* Fetch the CU's base address.  */
63166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  Dwarf_Die cudie = CUDIE (attr->cu);
63266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
63366eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  /* Find the base address of the compilation unit.  It will
63466eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard     normally be specified by DW_AT_low_pc.  In DWARF-3 draft 4,
63566eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard     the base address could be overridden by DW_AT_entry_pc.  It's
63666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard     been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc
63766eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard     for compilation units with discontinuous ranges.  */
63866eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  Dwarf_Attribute attr_mem;
63966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  if (unlikely (INTUSE(dwarf_lowpc) (&cudie, basep) != 0)
64066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      && INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (&cudie,
64166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard						     DW_AT_entry_pc,
64266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard						     &attr_mem),
64366eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard				 basep) != 0)
64466eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    {
64566eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      if (INTUSE(dwarf_errno) () != 0)
64666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	return -1;
64766eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
64866eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      /* The compiler provided no base address when it should
64966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	 have.  Buggy GCC does this when it used absolute
65066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	 addresses in the location list and no DW_AT_ranges.  */
65166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      *basep = 0;
65266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    }
65366eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  return 0;
65466eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard}
65566eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
65666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaardstatic int
6571ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaardinitial_offset_base (Dwarf_Attribute *attr, ptrdiff_t *offset,
6581ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaard		     Dwarf_Addr *basep)
65966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard{
66066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  if (attr_base_address (attr, basep) != 0)
66166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    return -1;
66266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
66366eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  Dwarf_Word start_offset;
66466eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  if (__libdw_formptr (attr, IDX_debug_loc,
66566eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard		       DWARF_E_NO_LOCLIST,
66666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard		       NULL, &start_offset) == NULL)
66766eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    return -1;
66866eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
66966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  *offset = start_offset;
67066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  return 0;
67166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard}
67266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
67366eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaardstatic ptrdiff_t
674f6b93914662566bbbb974cc85ef686a9f6b41a42Chih-Hung Hsiehgetlocations_addr (Dwarf_Attribute *attr, ptrdiff_t offset,
675f6b93914662566bbbb974cc85ef686a9f6b41a42Chih-Hung Hsieh		   Dwarf_Addr *basep, Dwarf_Addr *startp, Dwarf_Addr *endp,
676f6b93914662566bbbb974cc85ef686a9f6b41a42Chih-Hung Hsieh		   Dwarf_Addr address, const Elf_Data *locs, Dwarf_Op **expr,
677f6b93914662566bbbb974cc85ef686a9f6b41a42Chih-Hung Hsieh		   size_t *exprlen)
67866eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard{
67966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  unsigned char *readp = locs->d_buf + offset;
68066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  unsigned char *readendp = locs->d_buf + locs->d_size;
68166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
68266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard next:
68366eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  if (readendp - readp < attr->cu->address_size * 2)
68466eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    {
68566eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    invalid:
68666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      __libdw_seterrno (DWARF_E_INVALID_DWARF);
68766eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      return -1;
68866eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    }
68966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
69066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  Dwarf_Addr begin;
69166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  Dwarf_Addr end;
69266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
69366eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  switch (__libdw_read_begin_end_pair_inc (attr->cu->dbg, IDX_debug_loc,
69466eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard					   &readp, attr->cu->address_size,
69566eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard					   &begin, &end, basep))
69666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    {
69766eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    case 0: /* got location range. */
69866eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      break;
69966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    case 1: /* base address setup. */
70066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      goto next;
70166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    case 2: /* end of loclist */
70266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      return 0;
70366eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    default: /* error */
70466eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      return -1;
70566eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    }
70666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
70766eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  if (readendp - readp < 2)
70866eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    goto invalid;
70966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
71066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  /* We have a location expression.  */
71166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  Dwarf_Block block;
71266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  block.length = read_2ubyte_unaligned_inc (attr->cu->dbg, readp);
71366eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  block.data = readp;
71466eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  if (readendp - readp < (ptrdiff_t) block.length)
71566eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    goto invalid;
71666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  readp += block.length;
71766eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
71866eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  *startp = *basep + begin;
71966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  *endp = *basep + end;
72066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
72166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  /* If address is minus one we want them all, otherwise only matching.  */
72266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  if (address != (Dwarf_Word) -1 && (address < *startp || address >= *endp))
72366eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    goto next;
72466eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
72566eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  if (getlocation (attr->cu, &block, expr, exprlen, IDX_debug_loc) != 0)
72666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    return -1;
72766eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
72866eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  return readp - (unsigned char *) locs->d_buf;
72966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard}
73066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
731b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperint
7321ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaarddwarf_getlocation_addr (Dwarf_Attribute *attr, Dwarf_Addr address,
7331ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaard			Dwarf_Op **llbufs, size_t *listlens, size_t maxlocs)
734b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
735b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (! attr_ok (attr))
736b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return -1;
737b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
738b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (llbufs == NULL)
739b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    maxlocs = SIZE_MAX;
740b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
741b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If it has a block form, it's a single location expression.  */
742b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Dwarf_Block block;
743b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (INTUSE(dwarf_formblock) (attr, &block) == 0)
744b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
745b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (maxlocs == 0)
746b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	return 0;
747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (llbufs != NULL &&
74899d2372b25d1231d786b70278478c7a112f2b27cUlrich Drepper	  getlocation (attr->cu, &block, &llbufs[0], &listlens[0],
7493e0f7d1d1b817040cef82f41879f471ab59b663eRoland McGrath		       cu_sec_idx (attr->cu)) != 0)
750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	return -1;
751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return listlens[0] == 0 ? 0 : 1;
752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
754b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int error = INTUSE(dwarf_errno) ();
755f64a44262134500154f96c368a7d3d6e59f593c6Roland McGrath  if (unlikely (error != DWARF_E_NO_BLOCK))
756b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
757b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      __libdw_seterrno (error);
758b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return -1;
759b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
760b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
761cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath  int result = check_constant_offset (attr, &llbufs[0], &listlens[0]);
762cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath  if (result != 1)
763cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath    return result ?: 1;
764cfdd86ed929c137eaca5dd49cd266bb739c6cdbdRoland McGrath
76566eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  Dwarf_Addr base, start, end;
76666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  Dwarf_Op *expr;
76766eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  size_t expr_len;
76866eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  ptrdiff_t off = 0;
76966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  size_t got = 0;
77066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
77166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  /* This is a true loclistptr, fetch the initial base address and offset.  */
77266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  if (initial_offset_base (attr, &off, &base) != 0)
773b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return -1;
774b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
77566eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  const Elf_Data *d = attr->cu->dbg->sectiondata[IDX_debug_loc];
77666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  if (d == NULL)
777b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
77866eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      __libdw_seterrno (DWARF_E_NO_LOCLIST);
77966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      return -1;
78066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    }
78166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
78266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  while (got < maxlocs
78366eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard         && (off = getlocations_addr (attr, off, &base, &start, &end,
78466eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard				   address, d, &expr, &expr_len)) > 0)
78566eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    {
78666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      /* This one matches the address.  */
78766eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      if (llbufs != NULL)
788b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
78966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	  llbufs[got] = expr;
79066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	  listlens[got] = expr_len;
791b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
79266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      ++got;
79366eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    }
794b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
79566eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  /* We might stop early, so off can be zero or positive on success.  */
79666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  if (off < 0)
79766eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    return -1;
798b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
79966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  return got;
80066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard}
80166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
80266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaardptrdiff_t
8031ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaarddwarf_getlocations (Dwarf_Attribute *attr, ptrdiff_t offset, Dwarf_Addr *basep,
8041ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaard		    Dwarf_Addr *startp, Dwarf_Addr *endp, Dwarf_Op **expr,
8051ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaard		    size_t *exprlen)
80666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard{
80766eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  if (! attr_ok (attr))
80866eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    return -1;
80966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
81066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  /* 1 is an invalid offset, meaning no more locations. */
81166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  if (offset == 1)
81266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    return 0;
81366eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
81466eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  if (offset == 0)
81566eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    {
81666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      /* If it has a block form, it's a single location expression.  */
81766eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      Dwarf_Block block;
81866eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      if (INTUSE(dwarf_formblock) (attr, &block) == 0)
819f64a44262134500154f96c368a7d3d6e59f593c6Roland McGrath	{
82066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	  if (getlocation (attr->cu, &block, expr, exprlen,
82166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard			   cu_sec_idx (attr->cu)) != 0)
82266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	    return -1;
82356bc0b83ea81b7e959aaa4e1d01f8b36f2804a52Ulrich Drepper
82466eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	  /* This is the one and only location covering everything. */
82566eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	  *startp = 0;
82666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	  *endp = -1;
82766eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	  return 1;
828f64a44262134500154f96c368a7d3d6e59f593c6Roland McGrath	}
829f64a44262134500154f96c368a7d3d6e59f593c6Roland McGrath
83066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      int error = INTUSE(dwarf_errno) ();
83166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      if (unlikely (error != DWARF_E_NO_BLOCK))
832b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
83366eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	  __libdw_seterrno (error);
83466eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	  return -1;
835b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
83666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
83766eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      int result = check_constant_offset (attr, expr, exprlen);
83866eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      if (result != 1)
83966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	{
84066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	  if (result == 0)
84166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	    {
84266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	      /* This is the one and only location covering everything. */
84366eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	      *startp = 0;
84466eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	      *endp = -1;
84566eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	      return 1;
84666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	    }
84766eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	  return result;
84866eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	}
84966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
85066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      /* We must be looking at a true loclistptr, fetch the initial
85166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	 base address and offset.  */
85266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      if (initial_offset_base (attr, &offset, basep) != 0)
85366eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard	return -1;
854b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
855b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
85666eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  const Elf_Data *d = attr->cu->dbg->sectiondata[IDX_debug_loc];
85766eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  if (d == NULL)
85866eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    {
85966eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      __libdw_seterrno (DWARF_E_NO_LOCLIST);
86066eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard      return -1;
86166eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard    }
86266eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard
86366eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard  return getlocations_addr (attr, offset, basep, startp, endp,
86466eaae9bcc1608efad65e3aa0204afbb3cb1a83dMark Wielaard			    (Dwarf_Word) -1, d, expr, exprlen);
865b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
866