1 /* Return location expression list.
2 Copyright (C) 2000-2010 Red Hat, Inc.
3 This file is part of Red Hat elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 2000.
6 Red Hat elfutils is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by the
8 Free Software Foundation; version 2 of the License.
10 Red Hat elfutils is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with Red Hat elfutils; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
19 In addition, as a special exception, Red Hat, Inc. gives You the
20 additional right to link the code of Red Hat elfutils with code licensed
21 under any Open Source Initiative certified open source license
22 (http://www.opensource.org/licenses/index.php) which requires the
23 distribution of source code with any binary distribution and to
24 distribute linked combinations of the two. Non-GPL Code permitted under
25 this exception must only link to the code of Red Hat elfutils through
26 those well defined interfaces identified in the file named EXCEPTION
27 found in the source code files (the "Approved Interfaces"). The files
28 of Non-GPL Code may instantiate templates or use macros or inline
29 functions from the Approved Interfaces without causing the resulting
30 work to be covered by the GNU General Public License. Only Red Hat,
31 Inc. may make changes or additions to the list of Approved Interfaces.
32 Red Hat's grant of this exception is conditioned upon your not adding
33 any new exceptions. If you wish to add a new Approved Interface or
34 exception, please contact Red Hat. You must obey the GNU General Public
35 License in all respects for all of the Red Hat elfutils code and other
36 code used in conjunction with Red Hat elfutils except the Non-GPL Code
37 covered by this exception. If you modify this file, you may extend this
38 exception to your version of the file, but you are not obligated to do
39 so. If you do not wish to provide this exception without modification,
40 you must delete this exception statement from your version and license
41 this file solely under the GPL without exception.
43 Red Hat elfutils is an included package of the Open Invention Network.
44 An included package of the Open Invention Network is a package for which
45 Open Invention Network licensees cross-license their patents. No patent
46 license is granted, either expressly or impliedly, by designation as an
47 included package. Should you wish to participate in the Open Invention
48 Network licensing program, please visit www.openinventionnetwork.com
49 <http://www.openinventionnetwork.com>. */
64 attr_ok (Dwarf_Attribute *attr)
69 /* Must be one of the attributes listed below. */
73 case DW_AT_data_member_location:
74 case DW_AT_vtable_elem_location:
75 case DW_AT_string_length:
76 case DW_AT_use_location:
77 case DW_AT_frame_base:
78 case DW_AT_return_addr:
79 case DW_AT_static_link:
83 __libdw_seterrno (DWARF_E_NO_LOCLIST);
102 loc_compare (const void *p1, const void *p2)
104 const struct loc_s *l1 = (const struct loc_s *) p1;
105 const struct loc_s *l2 = (const struct loc_s *) p2;
107 if ((uintptr_t) l1->addr < (uintptr_t) l2->addr)
109 if ((uintptr_t) l1->addr > (uintptr_t) l2->addr)
115 /* For each DW_OP_implicit_value, we store a special entry in the cache.
116 This points us directly to the block data for later fetching. */
118 store_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op,
121 struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s,
122 sizeof (struct loc_block_s), 1);
124 block->data = data + op->number2;
125 block->length = op->number;
126 (void) tsearch (block, cache, loc_compare);
130 dwarf_getlocation_implicit_value (attr, op, return_block)
131 Dwarf_Attribute *attr;
133 Dwarf_Block *return_block;
138 struct loc_block_s fake = { .addr = (void *) op };
139 struct loc_block_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
140 if (unlikely (found == NULL))
142 __libdw_seterrno (DWARF_E_NO_BLOCK);
146 return_block->length = (*found)->length;
147 return_block->data = (*found)->data;
151 /* DW_AT_data_member_location can be a constant as well as a loclistptr.
152 Only data[48] indicate a loclistptr. */
154 check_constant_offset (Dwarf_Attribute *attr,
155 Dwarf_Op **llbuf, size_t *listlen)
157 if (attr->code != DW_AT_data_member_location)
162 /* Punt for any non-constant form. */
175 /* Check whether we already cached this location. */
176 struct loc_s fake = { .addr = attr->valp };
177 struct loc_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
182 if (INTUSE(dwarf_formudata) (attr, &offset) != 0)
185 Dwarf_Op *result = libdw_alloc (attr->cu->dbg,
186 Dwarf_Op, sizeof (Dwarf_Op), 1);
188 result->atom = DW_OP_plus_uconst;
189 result->number = offset;
193 /* Insert a record in the search tree so we can find it again later. */
194 struct loc_s *newp = libdw_alloc (attr->cu->dbg,
195 struct loc_s, sizeof (struct loc_s),
197 newp->addr = attr->valp;
201 found = tsearch (newp, &attr->cu->locs, loc_compare);
204 assert ((*found)->nloc == 1);
208 *llbuf = (*found)->loc;
217 __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
218 unsigned int address_size, unsigned int ref_size,
219 void **cache, const Dwarf_Block *block,
220 bool cfap, bool valuep,
221 Dwarf_Op **llbuf, size_t *listlen, int sec_index)
223 /* Check whether we already looked at this list. */
224 struct loc_s fake = { .addr = block->data };
225 struct loc_s **found = tfind (&fake, cache, loc_compare);
228 /* We already saw it. */
229 *llbuf = (*found)->loc;
230 *listlen = (*found)->nloc;
234 assert (*listlen > 1);
235 assert ((*llbuf)[*listlen - 1].atom == DW_OP_stack_value);
241 const unsigned char *data = block->data;
242 const unsigned char *const end_data = data + block->length;
244 const struct { bool other_byte_order; } bo = { other_byte_order };
246 struct loclist *loclist = NULL;
248 /* Decode the opcodes. It is possible in some situations to have a
249 block of size zero. */
250 while (data < end_data)
252 struct loclist *newloc;
253 newloc = (struct loclist *) alloca (sizeof (struct loclist));
256 newloc->offset = data - block->data;
257 newloc->next = loclist;
261 switch ((newloc->atom = *data++))
264 /* Address, depends on address size of CU. */
265 if (__libdw_read_address_inc (dbg, sec_index, &data,
266 address_size, &newloc->number))
271 /* DW_FORM_ref_addr, depends on offset size of CU. */
272 if (__libdw_read_offset_inc (dbg, sec_index, &data, ref_size,
273 &newloc->number, IDX_debug_info, 0))
304 case DW_OP_lit0 ... DW_OP_lit31:
305 case DW_OP_reg0 ... DW_OP_reg31:
307 case DW_OP_push_object_address:
308 case DW_OP_call_frame_cfa:
309 case DW_OP_form_tls_address:
310 case DW_OP_GNU_push_tls_address:
311 case DW_OP_stack_value:
317 case DW_OP_deref_size:
318 case DW_OP_xderef_size:
319 if (unlikely (data >= end_data))
322 __libdw_seterrno (DWARF_E_INVALID_DWARF);
326 newloc->number = *data++;
330 if (unlikely (data >= end_data))
333 newloc->number = *((int8_t *) data);
338 if (unlikely (data + 2 > end_data))
341 newloc->number = read_2ubyte_unaligned_inc (&bo, data);
348 if (unlikely (data + 2 > end_data))
351 newloc->number = read_2sbyte_unaligned_inc (&bo, data);
355 if (unlikely (data + 4 > end_data))
358 newloc->number = read_4ubyte_unaligned_inc (&bo, data);
363 if (unlikely (data + 4 > end_data))
366 newloc->number = read_4sbyte_unaligned_inc (&bo, data);
370 if (unlikely (data + 8 > end_data))
373 newloc->number = read_8ubyte_unaligned_inc (&bo, data);
377 if (unlikely (data + 8 > end_data))
380 newloc->number = read_8sbyte_unaligned_inc (&bo, data);
384 case DW_OP_plus_uconst:
387 /* XXX Check size. */
388 get_uleb128 (newloc->number, data);
392 case DW_OP_breg0 ... DW_OP_breg31:
394 /* XXX Check size. */
395 get_sleb128 (newloc->number, data);
399 /* XXX Check size. */
400 get_uleb128 (newloc->number, data);
401 get_sleb128 (newloc->number2, data);
404 case DW_OP_bit_piece:
405 /* XXX Check size. */
406 get_uleb128 (newloc->number, data);
407 get_uleb128 (newloc->number2, data);
410 case DW_OP_implicit_value:
411 /* This cannot be used in a CFI expression. */
412 if (unlikely (dbg == NULL))
415 /* XXX Check size. */
416 get_uleb128 (newloc->number, data); /* Block length. */
417 if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number))
419 newloc->number2 = data - block->data; /* Relative block offset. */
420 data += newloc->number; /* Skip the block. */
423 case DW_OP_GNU_implicit_pointer:
424 /* DW_FORM_ref_addr, depends on offset size of CU. */
425 if (__libdw_read_offset_inc (dbg, sec_index, &data, ref_size,
426 &newloc->number, IDX_debug_info, 0))
428 /* XXX Check size. */
429 get_uleb128 (newloc->number2, data); /* Byte offset. */
437 if (unlikely (n == 0))
439 /* This is not allowed.
447 struct loclist *newloc;
448 newloc = (struct loclist *) alloca (sizeof (struct loclist));
449 newloc->atom = DW_OP_stack_value;
452 newloc->offset = data - block->data;
453 newloc->next = loclist;
461 /* Allocate the array. */
464 result = libdw_alloc (dbg, Dwarf_Op, sizeof (Dwarf_Op), n);
467 result = malloc (sizeof *result * n);
471 __libdw_seterrno (DWARF_E_NOMEM);
476 /* Store the result. */
482 /* Synthesize the operation to push the CFA before the expression. */
484 result[0].atom = DW_OP_call_frame_cfa;
485 result[0].number = 0;
486 result[0].number2 = 0;
487 result[0].offset = -1;
492 /* We populate the array from the back since the list is backwards. */
494 result[n].atom = loclist->atom;
495 result[n].number = loclist->number;
496 result[n].number2 = loclist->number2;
497 result[n].offset = loclist->offset;
499 if (result[n].atom == DW_OP_implicit_value)
500 store_implicit_value (dbg, cache, &result[n], block->data);
502 loclist = loclist->next;
506 /* Insert a record in the search tree so that we can find it again later. */
509 newp = libdw_alloc (dbg, struct loc_s, sizeof (struct loc_s), 1);
512 newp = malloc (sizeof *newp);
520 newp->addr = block->data;
522 newp->nloc = *listlen;
523 (void) tsearch (newp, cache, loc_compare);
530 getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
531 Dwarf_Op **llbuf, size_t *listlen, int sec_index)
533 return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order,
534 cu->address_size, (cu->version == 2
539 llbuf, listlen, sec_index);
543 dwarf_getlocation (attr, llbuf, listlen)
544 Dwarf_Attribute *attr;
548 if (! attr_ok (attr))
551 int result = check_constant_offset (attr, llbuf, listlen);
555 /* If it has a block form, it's a single location expression. */
557 if (INTUSE(dwarf_formblock) (attr, &block) != 0)
560 return getlocation (attr->cu, &block, llbuf, listlen, cu_sec_idx (attr->cu));
564 dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs)
565 Dwarf_Attribute *attr;
571 if (! attr_ok (attr))
577 /* If it has a block form, it's a single location expression. */
579 if (INTUSE(dwarf_formblock) (attr, &block) == 0)
583 if (llbufs != NULL &&
584 getlocation (attr->cu, &block, &llbufs[0], &listlens[0],
585 cu_sec_idx (attr->cu)) != 0)
587 return listlens[0] == 0 ? 0 : 1;
590 int error = INTUSE(dwarf_errno) ();
591 if (unlikely (error != DWARF_E_NO_BLOCK))
593 __libdw_seterrno (error);
597 int result = check_constant_offset (attr, &llbufs[0], &listlens[0]);
602 unsigned char *readp = __libdw_formptr (attr, IDX_debug_loc,
603 DWARF_E_NO_LOCLIST, &endp, NULL);
607 Dwarf_Addr base = (Dwarf_Addr) -1;
609 while (got < maxlocs)
611 if (endp - readp < attr->cu->address_size * 2)
614 __libdw_seterrno (DWARF_E_INVALID_DWARF);
622 = __libdw_read_begin_end_pair_inc (attr->cu->dbg, IDX_debug_loc,
623 &readp, attr->cu->address_size,
624 &begin, &end, &base);
625 if (status == 2) /* End of list entry. */
627 else if (status == 1) /* Base address selected. */
632 if (endp - readp < 2)
635 /* We have a location expression. */
636 block.length = read_2ubyte_unaligned_inc (attr->cu->dbg, readp);
638 if (endp - readp < (ptrdiff_t) block.length)
640 readp += block.length;
642 if (base == (Dwarf_Addr) -1)
644 /* Fetch the CU's base address. */
645 Dwarf_Die cudie = CUDIE (attr->cu);
647 /* Find the base address of the compilation unit. It will
648 normally be specified by DW_AT_low_pc. In DWARF-3 draft 4,
649 the base address could be overridden by DW_AT_entry_pc. It's
650 been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc
651 for compilation units with discontinuous ranges. */
652 Dwarf_Attribute attr_mem;
653 if (unlikely (INTUSE(dwarf_lowpc) (&cudie, &base) != 0)
654 && INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (&cudie,
659 if (INTUSE(dwarf_errno) () != 0)
662 /* The compiler provided no base address when it should
663 have. Buggy GCC does this when it used absolute
664 addresses in the location list and no DW_AT_ranges. */
669 if (address >= base + begin && address < base + end)
671 /* This one matches the address. */
673 && unlikely (getlocation (attr->cu, &block,
674 &llbufs[got], &listlens[got],
675 IDX_debug_loc) != 0))