125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Return location expression list.
225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Copyright (C) 2000-2010 Red Hat, Inc.
325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   This file is part of Red Hat elfutils.
425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is free software; you can redistribute it and/or modify
725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   it under the terms of the GNU General Public License as published by the
825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Free Software Foundation; version 2 of the License.
925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is distributed in the hope that it will be useful, but
1125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   General Public License for more details.
1425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   You should have received a copy of the GNU General Public License along
1625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   with Red Hat elfutils; if not, write to the Free Software Foundation,
1725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   In addition, as a special exception, Red Hat, Inc. gives You the
2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   additional right to link the code of Red Hat elfutils with code licensed
2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   under any Open Source Initiative certified open source license
2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   (http://www.opensource.org/licenses/index.php) which requires the
2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   distribution of source code with any binary distribution and to
2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   distribute linked combinations of the two.  Non-GPL Code permitted under
2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   this exception must only link to the code of Red Hat elfutils through
2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   those well defined interfaces identified in the file named EXCEPTION
2725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   found in the source code files (the "Approved Interfaces").  The files
2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   of Non-GPL Code may instantiate templates or use macros or inline
2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   functions from the Approved Interfaces without causing the resulting
3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   work to be covered by the GNU General Public License.  Only Red Hat,
3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Inc. may make changes or additions to the list of Approved Interfaces.
3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat's grant of this exception is conditioned upon your not adding
3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   any new exceptions.  If you wish to add a new Approved Interface or
3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   exception, please contact Red Hat.  You must obey the GNU General Public
3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   License in all respects for all of the Red Hat elfutils code and other
3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   code used in conjunction with Red Hat elfutils except the Non-GPL Code
3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   covered by this exception.  If you modify this file, you may extend this
3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   exception to your version of the file, but you are not obligated to do
3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   so.  If you do not wish to provide this exception without modification,
4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   you must delete this exception statement from your version and license
4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   this file solely under the GPL without exception.
4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is an included package of the Open Invention Network.
4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   An included package of the Open Invention Network is a package for which
4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Open Invention Network licensees cross-license their patents.  No patent
4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   license is granted, either expressly or impliedly, by designation as an
4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   included package.  Should you wish to participate in the Open Invention
4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Network licensing program, please visit www.openinventionnetwork.com
4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   <http://www.openinventionnetwork.com>.  */
5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H
5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h>
5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <dwarf.h>
5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <search.h>
5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdlib.h>
5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <assert.h>
5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libdwP.h>
6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool
6425b3c049e70834cf33790a28643ab058b507b35cBen Chengattr_ok (Dwarf_Attribute *attr)
6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (attr == NULL)
6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return false;
6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Must be one of the attributes listed below.  */
7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (attr->code)
7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_AT_location:
7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_AT_data_member_location:
7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_AT_vtable_elem_location:
7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_AT_string_length:
7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_AT_use_location:
7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_AT_frame_base:
7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_AT_return_addr:
7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_AT_static_link:
8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libdw_seterrno (DWARF_E_NO_LOCLIST);
8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return false;
8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return true;
8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9125b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct loclist
9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint8_t atom;
9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Word number;
9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Word number2;
9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Word offset;
9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct loclist *next;
9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
10225b3c049e70834cf33790a28643ab058b507b35cBen Chengloc_compare (const void *p1, const void *p2)
10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const struct loc_s *l1 = (const struct loc_s *) p1;
10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const struct loc_s *l2 = (const struct loc_s *) p2;
10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((uintptr_t) l1->addr < (uintptr_t) l2->addr)
10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((uintptr_t) l1->addr > (uintptr_t) l2->addr)
11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return 1;
11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* For each DW_OP_implicit_value, we store a special entry in the cache.
11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   This points us directly to the block data for later fetching.  */
11725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
11825b3c049e70834cf33790a28643ab058b507b35cBen Chengstore_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op,
11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      unsigned char *data)
12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s,
12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   sizeof (struct loc_block_s), 1);
12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  block->addr = op;
12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  block->data = data + op->number2;
12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  block->length = op->number;
12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) tsearch (block, cache, loc_compare);
12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12925b3c049e70834cf33790a28643ab058b507b35cBen Chengint
13025b3c049e70834cf33790a28643ab058b507b35cBen Chengdwarf_getlocation_implicit_value (attr, op, return_block)
13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     Dwarf_Attribute *attr;
13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng     const Dwarf_Op *op;
13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     Dwarf_Block *return_block;
13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (attr == NULL)
13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct loc_block_s fake = { .addr = (void *) op };
13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct loc_block_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (found == NULL))
14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libdw_seterrno (DWARF_E_NO_BLOCK);
14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return -1;
14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return_block->length = (*found)->length;
14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return_block->data = (*found)->data;
14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* DW_AT_data_member_location can be a constant as well as a loclistptr.
15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Only data[48] indicate a loclistptr.  */
15325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
15425b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_constant_offset (Dwarf_Attribute *attr,
15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       Dwarf_Op **llbuf, size_t *listlen)
15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (attr->code != DW_AT_data_member_location)
15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return 1;
15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (attr->form)
16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Punt for any non-constant form.  */
16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 1;
16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_data1:
16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_data2:
16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_data4:
16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_data8:
17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_sdata:
17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_udata:
17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Check whether we already cached this location.  */
17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct loc_s fake = { .addr = attr->valp };
17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct loc_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (found == NULL)
18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word offset;
18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (INTUSE(dwarf_formudata) (attr, &offset) != 0)
18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return -1;
18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Op *result = libdw_alloc (attr->cu->dbg,
18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      Dwarf_Op, sizeof (Dwarf_Op), 1);
18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result->atom = DW_OP_plus_uconst;
18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result->number = offset;
19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result->number2 = 0;
19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result->offset = 0;
19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Insert a record in the search tree so we can find it again later.  */
19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      struct loc_s *newp = libdw_alloc (attr->cu->dbg,
19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng					struct loc_s, sizeof (struct loc_s),
19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng					1);
19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newp->addr = attr->valp;
19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newp->loc = result;
19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newp->nloc = 1;
20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      found = tsearch (newp, &attr->cu->locs, loc_compare);
20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert ((*found)->nloc == 1);
20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (llbuf != NULL)
20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *llbuf = (*found)->loc;
20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *listlen = 1;
21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21525b3c049e70834cf33790a28643ab058b507b35cBen Chengint
21625b3c049e70834cf33790a28643ab058b507b35cBen Chenginternal_function
21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng__libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   unsigned int address_size, unsigned int ref_size,
21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   void **cache, const Dwarf_Block *block,
22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   bool cfap, bool valuep,
22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   Dwarf_Op **llbuf, size_t *listlen, int sec_index)
22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Check whether we already looked at this list.  */
22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct loc_s fake = { .addr = block->data };
22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct loc_s **found = tfind (&fake, cache, loc_compare);
22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (found != NULL)
22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We already saw it.  */
22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *llbuf = (*found)->loc;
23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *listlen = (*found)->nloc;
23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (valuep)
23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  assert (*listlen > 1);
23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  assert ((*llbuf)[*listlen - 1].atom == DW_OP_stack_value);
23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 0;
23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *data = block->data;
24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *const end_data = data + block->length;
24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const struct { bool other_byte_order; } bo = { other_byte_order };
24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct loclist *loclist = NULL;
24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int n = 0;
24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Decode the opcodes.  It is possible in some situations to have a
24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     block of size zero.  */
25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (data < end_data)
25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      struct loclist *newloc;
25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newloc = (struct loclist *) alloca (sizeof (struct loclist));
25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newloc->number = 0;
25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newloc->number2 = 0;
25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newloc->offset = data - block->data;
25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newloc->next = loclist;
25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      loclist = newloc;
25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++n;
26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch ((newloc->atom = *data++))
26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_addr:
26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Address, depends on address size of CU.  */
26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (__libdw_read_address_inc (dbg, sec_index, &data,
26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng					address_size, &newloc->number))
26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return -1;
26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_call_ref:
27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* DW_FORM_ref_addr, depends on offset size of CU.  */
27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (__libdw_read_offset_inc (dbg, sec_index, &data, ref_size,
27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       &newloc->number, IDX_debug_info, 0))
27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return -1;
27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_deref:
27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_dup:
27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_drop:
28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_over:
28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_swap:
28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_rot:
28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_xderef:
28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_abs:
28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_and:
28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_div:
28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_minus:
28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_mod:
28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_mul:
29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_neg:
29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_not:
29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_or:
29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_plus:
29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_shl:
29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_shr:
29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_shra:
29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_xor:
29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_eq:
29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_ge:
30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_gt:
30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_le:
30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_lt:
30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_ne:
30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_lit0 ... DW_OP_lit31:
30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_reg0 ... DW_OP_reg31:
30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_nop:
30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_push_object_address:
30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_call_frame_cfa:
30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_form_tls_address:
31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_GNU_push_tls_address:
31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_stack_value:
31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* No operand.  */
31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const1u:
31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_pick:
31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_deref_size:
31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_xderef_size:
31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (data >= end_data))
32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    invalid:
32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return -1;
32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  newloc->number = *data++;
32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const1s:
33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (data >= end_data))
33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid;
33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  newloc->number = *((int8_t *) data);
33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++data;
33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const2u:
33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (data + 2 > end_data))
33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid;
34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  newloc->number = read_2ubyte_unaligned_inc (&bo, data);
34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const2s:
34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_skip:
34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_bra:
34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_call2:
34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (data + 2 > end_data))
34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid;
35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  newloc->number = read_2sbyte_unaligned_inc (&bo, data);
35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const4u:
35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (data + 4 > end_data))
35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid;
35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  newloc->number = read_4ubyte_unaligned_inc (&bo, data);
35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const4s:
36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_call4:
36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (data + 4 > end_data))
36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid;
36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  newloc->number = read_4sbyte_unaligned_inc (&bo, data);
36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const8u:
37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (data + 8 > end_data))
37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid;
37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  newloc->number = read_8ubyte_unaligned_inc (&bo, data);
37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const8s:
37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (data + 8 > end_data))
37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid;
37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  newloc->number = read_8sbyte_unaligned_inc (&bo, data);
38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_constu:
38425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_plus_uconst:
38525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_regx:
38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_piece:
38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* XXX Check size.  */
38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (newloc->number, data);
38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_consts:
39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_breg0 ... DW_OP_breg31:
39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_fbreg:
39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* XXX Check size.  */
39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_sleb128 (newloc->number, data);
39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_bregx:
39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* XXX Check size.  */
40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (newloc->number, data);
40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_sleb128 (newloc->number2, data);
40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_bit_piece:
40525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* XXX Check size.  */
40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (newloc->number, data);
40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (newloc->number2, data);
40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_implicit_value:
41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* This cannot be used in a CFI expression.  */
41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (dbg == NULL))
41325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid;
41425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
41525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* XXX Check size.  */
41625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (newloc->number, data); /* Block length.  */
41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number))
41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid;
41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  newloc->number2 = data - block->data; /* Relative block offset.  */
42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += newloc->number;		/* Skip the block.  */
42125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
42225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
42325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_GNU_implicit_pointer:
42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* DW_FORM_ref_addr, depends on offset size of CU.  */
42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (__libdw_read_offset_inc (dbg, sec_index, &data, ref_size,
42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       &newloc->number, IDX_debug_info, 0))
42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return -1;
42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* XXX Check size.  */
42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (newloc->number2, data); /* Byte offset.  */
43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
43125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
43225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
43325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  goto invalid;
43425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
43525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
43625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
43725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (n == 0))
43825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
43925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This is not allowed.
44025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
44125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 XXX Is it?  */
44225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      goto invalid;
44325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
44425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (valuep)
44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      struct loclist *newloc;
44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newloc = (struct loclist *) alloca (sizeof (struct loclist));
44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newloc->atom = DW_OP_stack_value;
45025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newloc->number = 0;
45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newloc->number2 = 0;
45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newloc->offset = data - block->data;
45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newloc->next = loclist;
45425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      loclist = newloc;
45525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++n;
45625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
45725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (cfap)
45925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    ++n;
46025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
46125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Allocate the array.  */
46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Op *result;
46325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (dbg != NULL)
46425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    result = libdw_alloc (dbg, Dwarf_Op, sizeof (Dwarf_Op), n);
46525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
46625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
46725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result = malloc (sizeof *result * n);
46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (result == NULL)
46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	nomem:
47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  __libdw_seterrno (DWARF_E_NOMEM);
47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return -1;
47325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
47525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
47625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Store the result.  */
47725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *llbuf = result;
47825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *listlen = n;
47925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
48025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (cfap)
48125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
48225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Synthesize the operation to push the CFA before the expression.  */
48325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      --n;
48425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result[0].atom = DW_OP_call_frame_cfa;
48525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result[0].number = 0;
48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result[0].number2 = 0;
48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result[0].offset = -1;
48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
48925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  do
49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
49225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We populate the array from the back since the list is backwards.  */
49325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      --n;
49425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result[n].atom = loclist->atom;
49525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result[n].number = loclist->number;
49625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result[n].number2 = loclist->number2;
49725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result[n].offset = loclist->offset;
49825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (result[n].atom == DW_OP_implicit_value)
50025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	store_implicit_value (dbg, cache, &result[n], block->data);
50125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      loclist = loclist->next;
50325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
50425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (n > 0);
50525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Insert a record in the search tree so that we can find it again later.  */
50725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct loc_s *newp;
50825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (dbg != NULL)
50925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    newp = libdw_alloc (dbg, struct loc_s, sizeof (struct loc_s), 1);
51025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
51125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
51225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newp = malloc (sizeof *newp);
51325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (newp == NULL)
51425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
51525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (result);
51625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  goto nomem;
51725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
51825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
51925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
52025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  newp->addr = block->data;
52125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  newp->loc = result;
52225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  newp->nloc = *listlen;
52325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) tsearch (newp, cache, loc_compare);
52425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
52525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We did it.  */
52625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
52725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
52825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
52925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
53025b3c049e70834cf33790a28643ab058b507b35cBen Chenggetlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
53125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     Dwarf_Op **llbuf, size_t *listlen, int sec_index)
53225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
53325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order,
53425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    cu->address_size, (cu->version == 2
53525b3c049e70834cf33790a28643ab058b507b35cBen Cheng						       ? cu->address_size
53625b3c049e70834cf33790a28643ab058b507b35cBen Cheng						       : cu->offset_size),
53725b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    &cu->locs, block,
53825b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    false, false,
53925b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    llbuf, listlen, sec_index);
54025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
54125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
54225b3c049e70834cf33790a28643ab058b507b35cBen Chengint
54325b3c049e70834cf33790a28643ab058b507b35cBen Chengdwarf_getlocation (attr, llbuf, listlen)
54425b3c049e70834cf33790a28643ab058b507b35cBen Cheng     Dwarf_Attribute *attr;
54525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     Dwarf_Op **llbuf;
54625b3c049e70834cf33790a28643ab058b507b35cBen Cheng     size_t *listlen;
54725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
54825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (! attr_ok (attr))
54925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
55025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
55125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int result = check_constant_offset (attr, llbuf, listlen);
55225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (result != 1)
55325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return result;
55425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
55525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* If it has a block form, it's a single location expression.  */
55625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Block block;
55725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (INTUSE(dwarf_formblock) (attr, &block) != 0)
55825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
55925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
56025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return getlocation (attr->cu, &block, llbuf, listlen, cu_sec_idx (attr->cu));
56125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
56225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
56325b3c049e70834cf33790a28643ab058b507b35cBen Chengint
56425b3c049e70834cf33790a28643ab058b507b35cBen Chengdwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs)
56525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     Dwarf_Attribute *attr;
56625b3c049e70834cf33790a28643ab058b507b35cBen Cheng     Dwarf_Addr address;
56725b3c049e70834cf33790a28643ab058b507b35cBen Cheng     Dwarf_Op **llbufs;
56825b3c049e70834cf33790a28643ab058b507b35cBen Cheng     size_t *listlens;
56925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     size_t maxlocs;
57025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (! attr_ok (attr))
57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
57325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
57425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (llbufs == NULL)
57525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    maxlocs = SIZE_MAX;
57625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
57725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* If it has a block form, it's a single location expression.  */
57825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Block block;
57925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (INTUSE(dwarf_formblock) (attr, &block) == 0)
58025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
58125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (maxlocs == 0)
58225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return 0;
58325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (llbufs != NULL &&
58425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  getlocation (attr->cu, &block, &llbufs[0], &listlens[0],
58525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       cu_sec_idx (attr->cu)) != 0)
58625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return -1;
58725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return listlens[0] == 0 ? 0 : 1;
58825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
58925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
59025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int error = INTUSE(dwarf_errno) ();
59125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (error != DWARF_E_NO_BLOCK))
59225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
59325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libdw_seterrno (error);
59425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return -1;
59525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
59625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
59725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int result = check_constant_offset (attr, &llbufs[0], &listlens[0]);
59825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (result != 1)
59925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return result ?: 1;
60025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
60125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned char *endp;
60225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned char *readp = __libdw_formptr (attr, IDX_debug_loc,
60325b3c049e70834cf33790a28643ab058b507b35cBen Cheng					  DWARF_E_NO_LOCLIST, &endp, NULL);
60425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (readp == NULL)
60525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
60625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
60725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Addr base = (Dwarf_Addr) -1;
60825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t got = 0;
60925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (got < maxlocs)
61025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
61125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (endp - readp < attr->cu->address_size * 2)
61225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
61325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	invalid:
61425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
61525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return -1;
61625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
61725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
61825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Addr begin;
61925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Addr end;
62025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
62125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int status
62225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	= __libdw_read_begin_end_pair_inc (attr->cu->dbg, IDX_debug_loc,
62325b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   &readp, attr->cu->address_size,
62425b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   &begin, &end, &base);
62525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (status == 2) /* End of list entry.  */
62625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
62725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (status == 1) /* Base address selected.  */
62825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
62925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (status < 0)
63025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return status;
63125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
63225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (endp - readp < 2)
63325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid;
63425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
63525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We have a location expression.  */
63625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      block.length = read_2ubyte_unaligned_inc (attr->cu->dbg, readp);
63725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      block.data = readp;
63825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (endp - readp < (ptrdiff_t) block.length)
63925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid;
64025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += block.length;
64125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
64225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (base == (Dwarf_Addr) -1)
64325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
64425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Fetch the CU's base address.  */
64525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Dwarf_Die cudie = CUDIE (attr->cu);
64625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
64725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Find the base address of the compilation unit.  It will
64825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     normally be specified by DW_AT_low_pc.  In DWARF-3 draft 4,
64925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     the base address could be overridden by DW_AT_entry_pc.  It's
65025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc
65125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     for compilation units with discontinuous ranges.  */
65225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Dwarf_Attribute attr_mem;
65325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (INTUSE(dwarf_lowpc) (&cudie, &base) != 0)
65425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (&cudie,
65525b3c049e70834cf33790a28643ab058b507b35cBen Cheng							     DW_AT_entry_pc,
65625b3c049e70834cf33790a28643ab058b507b35cBen Cheng							     &attr_mem),
65725b3c049e70834cf33790a28643ab058b507b35cBen Cheng					 &base) != 0)
65825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
65925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (INTUSE(dwarf_errno) () != 0)
66025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		return -1;
66125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
66225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* The compiler provided no base address when it should
66325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 have.  Buggy GCC does this when it used absolute
66425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 addresses in the location list and no DW_AT_ranges.  */
66525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      base = 0;
66625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
66725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
66825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
66925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (address >= base + begin && address < base + end)
67025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
67125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* This one matches the address.  */
67225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (llbufs != NULL
67325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && unlikely (getlocation (attr->cu, &block,
67425b3c049e70834cf33790a28643ab058b507b35cBen Cheng					&llbufs[got], &listlens[got],
67525b3c049e70834cf33790a28643ab058b507b35cBen Cheng					IDX_debug_loc) != 0))
67625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return -1;
67725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++got;
67825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
67925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
68025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
68125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return got;
68225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
683