Blame tests/varlocs.c

Packit Service 97d2fb
/* Test program for dwarf location functions.
Packit Service 97d2fb
   Copyright (C) 2013, 2015, 2017, 2018 Red Hat, Inc.
Packit Service 97d2fb
   This file is part of elfutils.
Packit Service 97d2fb
Packit Service 97d2fb
   This file is free software; you can redistribute it and/or modify
Packit Service 97d2fb
   it under the terms of the GNU General Public License as published by
Packit Service 97d2fb
   the Free Software Foundation; either version 3 of the License, or
Packit Service 97d2fb
   (at your option) any later version.
Packit Service 97d2fb
Packit Service 97d2fb
   elfutils is distributed in the hope that it will be useful, but
Packit Service 97d2fb
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 97d2fb
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 97d2fb
   GNU General Public License for more details.
Packit Service 97d2fb
Packit Service 97d2fb
   You should have received a copy of the GNU General Public License
Packit Service 97d2fb
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit Service 97d2fb
Packit Service 97d2fb
#include <config.h>
Packit Service 97d2fb
#include <assert.h>
Packit Service 97d2fb
#include <argp.h>
Packit Service 97d2fb
#include <inttypes.h>
Packit Service 97d2fb
#include <errno.h>
Packit Service 97d2fb
#include ELFUTILS_HEADER(dw)
Packit Service 97d2fb
#include ELFUTILS_HEADER(dwfl)
Packit Service 97d2fb
#include <dwarf.h>
Packit Service 97d2fb
#include <stdio.h>
Packit Service 97d2fb
#include <stdlib.h>
Packit Service 97d2fb
#include <string.h>
Packit Service 97d2fb
#include <sys/types.h>
Packit Service 97d2fb
#include <sys/stat.h>
Packit Service 97d2fb
#include <fcntl.h>
Packit Service 97d2fb
#include <unistd.h>
Packit Service 97d2fb
Packit Service 97d2fb
#include "system.h"
Packit Service 97d2fb
#include "../libdw/known-dwarf.h"
Packit Service 97d2fb
Packit Service 97d2fb
// The Dwarf, Dwarf_CFIs and address bias of
Packit Service 97d2fb
// cfi table to adjust DWARF addresses against.
Packit Service 97d2fb
// Needed for DW_OP_call_frame_cfa.
Packit Service 97d2fb
static Dwarf *dw;
Packit Service 97d2fb
Dwarf_CFI *cfi_debug;
Packit Service 97d2fb
Dwarf_Addr cfi_debug_bias;
Packit Service 97d2fb
Dwarf_CFI *cfi_eh;
Packit Service 97d2fb
Dwarf_Addr cfi_eh_bias;
Packit Service 97d2fb
Packit Service 97d2fb
bool is_ET_REL;
Packit Service 97d2fb
bool is_debug;
Packit Service 97d2fb
Packit Service 97d2fb
// Whether the current function has a DW_AT_frame_base defined.
Packit Service 97d2fb
// Needed for DW_OP_fbreg.
Packit Service 97d2fb
bool has_frame_base;
Packit Service 97d2fb
Packit Service 97d2fb
static void
Packit Service 97d2fb
print_die (Dwarf_Die *die, const char *what, int indent)
Packit Service 97d2fb
{
Packit Service 97d2fb
  Dwarf_Addr entrypc;
Packit Service 97d2fb
  const char *name = dwarf_diename (die) ?: "<unknown>";
Packit Service 97d2fb
  if (dwarf_entrypc (die, &entrypc) == 0)
Packit Service 97d2fb
    printf ("%*s[%" PRIx64 "] %s '%s'@%" PRIx64 "\n", indent * 2, "",
Packit Service 97d2fb
	    dwarf_dieoffset (die), what, name, entrypc);
Packit Service 97d2fb
  else
Packit Service 97d2fb
    printf ("%*s[%" PRIx64 "] %s '%s'\n", indent * 2, "",
Packit Service 97d2fb
	    dwarf_dieoffset (die), what, name);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static const char *
Packit Service 97d2fb
dwarf_encoding_string (unsigned int code)
Packit Service 97d2fb
{
Packit Service 97d2fb
  static const char *const known[] =
Packit Service 97d2fb
    {
Packit Service 97d2fb
#define DWARF_ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
Packit Service 97d2fb
      DWARF_ALL_KNOWN_DW_ATE
Packit Service 97d2fb
#undef DWARF_ONE_KNOWN_DW_ATE
Packit Service 97d2fb
    };
Packit Service 97d2fb
Packit Service 97d2fb
  if (likely (code < sizeof (known) / sizeof (known[0])))
Packit Service 97d2fb
    return known[code];
Packit Service 97d2fb
Packit Service 97d2fb
  return NULL;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static const char *
Packit Service 97d2fb
dwarf_tag_string (unsigned int tag)
Packit Service 97d2fb
{
Packit Service 97d2fb
  switch (tag)
Packit Service 97d2fb
    {
Packit Service 97d2fb
#define DWARF_ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
Packit Service 97d2fb
      DWARF_ALL_KNOWN_DW_TAG
Packit Service 97d2fb
#undef DWARF_ONE_KNOWN_DW_TAG
Packit Service 97d2fb
    default:
Packit Service 97d2fb
      return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static const char *
Packit Service 97d2fb
dwarf_attr_string (unsigned int attrnum)
Packit Service 97d2fb
{
Packit Service 97d2fb
  switch (attrnum)
Packit Service 97d2fb
    {
Packit Service 97d2fb
#define DWARF_ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
Packit Service 97d2fb
      DWARF_ALL_KNOWN_DW_AT
Packit Service 97d2fb
#undef DWARF_ONE_KNOWN_DW_AT
Packit Service 97d2fb
    default:
Packit Service 97d2fb
      return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static const char *
Packit Service 97d2fb
dwarf_form_string (unsigned int form)
Packit Service 97d2fb
{
Packit Service 97d2fb
  switch (form)
Packit Service 97d2fb
    {
Packit Service 97d2fb
#define DWARF_ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME;
Packit Service 97d2fb
      DWARF_ALL_KNOWN_DW_FORM
Packit Service 97d2fb
#undef DWARF_ONE_KNOWN_DW_FORM
Packit Service 97d2fb
    default:
Packit Service 97d2fb
      return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
/* BASE must be a base type DIE referenced by a typed DWARF expression op.  */
Packit Service 97d2fb
static void
Packit Service 97d2fb
print_base_type (Dwarf_Die *base)
Packit Service 97d2fb
{
Packit Service 97d2fb
  if (dwarf_tag (base) != DW_TAG_base_type)
Packit Service 97d2fb
    error (EXIT_FAILURE, 0, "not a base type");
Packit Service 97d2fb
Packit Service 97d2fb
  Dwarf_Attribute encoding;
Packit Service 97d2fb
  Dwarf_Word enctype = 0;
Packit Service 97d2fb
  if (dwarf_attr (base, DW_AT_encoding, &encoding) == NULL
Packit Service 97d2fb
      || dwarf_formudata (&encoding, &enctype) != 0)
Packit Service 97d2fb
    error (EXIT_FAILURE, 0, "base type without encoding");
Packit Service 97d2fb
Packit Service 97d2fb
  Dwarf_Attribute bsize;
Packit Service 97d2fb
  Dwarf_Word bits;
Packit Service 97d2fb
  if (dwarf_attr (base, DW_AT_byte_size, &bsize) != NULL
Packit Service 97d2fb
      && dwarf_formudata (&bsize, &bits) == 0)
Packit Service 97d2fb
    bits *= 8;
Packit Service 97d2fb
  else if (dwarf_attr (base, DW_AT_bit_size, &bsize) == NULL
Packit Service 97d2fb
	   || dwarf_formudata (&bsize, &bits) != 0)
Packit Service 97d2fb
    error (EXIT_FAILURE, 0, "base type without byte or bit size");
Packit Service 97d2fb
Packit Service 97d2fb
  printf ("{%s,%s,%" PRIu64 "@[%" PRIx64 "]}",
Packit Service 97d2fb
	  dwarf_diename (base),
Packit Service 97d2fb
	  dwarf_encoding_string (enctype),
Packit Service 97d2fb
	  bits,
Packit Service 97d2fb
	  dwarf_dieoffset (base));
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static const char *
Packit Service 97d2fb
dwarf_opcode_string (unsigned int code)
Packit Service 97d2fb
{
Packit Service 97d2fb
  static const char *const known[] =
Packit Service 97d2fb
    {
Packit Service 97d2fb
#define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
Packit Service 97d2fb
      DWARF_ALL_KNOWN_DW_OP
Packit Service 97d2fb
#undef DWARF_ONE_KNOWN_DW_OP
Packit Service 97d2fb
    };
Packit Service 97d2fb
Packit Service 97d2fb
  if (likely (code < sizeof (known) / sizeof (known[0])))
Packit Service 97d2fb
    return known[code];
Packit Service 97d2fb
Packit Service 97d2fb
  return NULL;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
// Forward reference for print_expr_block.
Packit Service 97d2fb
static void print_expr (Dwarf_Attribute *, Dwarf_Op *, Dwarf_Addr, int);
Packit Service 97d2fb
Packit Service 97d2fb
static void
Packit Service 97d2fb
print_expr_block (Dwarf_Attribute *attr, Dwarf_Op *exprs, int len,
Packit Service 97d2fb
		  Dwarf_Addr addr, int depth)
Packit Service 97d2fb
{
Packit Service 97d2fb
  printf ("{");
Packit Service 97d2fb
  for (int i = 0; i < len; i++)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      print_expr (attr, &exprs[i], addr, depth);
Packit Service 97d2fb
      printf ("%s", (i + 1 < len ? ", " : ""));
Packit Service 97d2fb
    }
Packit Service 97d2fb
  printf ("}");
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static void
Packit Service 97d2fb
print_expr_block_addrs (Dwarf_Attribute *attr,
Packit Service 97d2fb
			Dwarf_Addr begin, Dwarf_Addr end,
Packit Service 97d2fb
			Dwarf_Op *exprs, int len)
Packit Service 97d2fb
{
Packit Service 97d2fb
  printf ("      [%" PRIx64 ",%" PRIx64 ") ", begin, end);
Packit Service 97d2fb
  print_expr_block (attr, exprs, len, begin, 0);
Packit Service 97d2fb
  printf ("\n");
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static void
Packit Service 97d2fb
print_expr (Dwarf_Attribute *attr, Dwarf_Op *expr, Dwarf_Addr addr, int depth)
Packit Service 97d2fb
{
Packit Service 97d2fb
#define MAX_DEPTH 64
Packit Service 97d2fb
  if (depth++ > MAX_DEPTH)
Packit Service 97d2fb
    error (EXIT_FAILURE, 0, "print_expr recursion depth exceeded");
Packit Service 97d2fb
Packit Service 97d2fb
  uint8_t atom = expr->atom;
Packit Service 97d2fb
  const char *opname = dwarf_opcode_string (atom);
Packit Service 97d2fb
  assert (opname != NULL);
Packit Service 97d2fb
Packit Service 97d2fb
  switch (atom)
Packit Service 97d2fb
    {
Packit Service 97d2fb
    case DW_OP_deref:
Packit Service 97d2fb
    case DW_OP_dup:
Packit Service 97d2fb
    case DW_OP_drop:
Packit Service 97d2fb
    case DW_OP_over:
Packit Service 97d2fb
    case DW_OP_swap:
Packit Service 97d2fb
    case DW_OP_rot:
Packit Service 97d2fb
    case DW_OP_xderef:
Packit Service 97d2fb
    case DW_OP_abs:
Packit Service 97d2fb
    case DW_OP_and:
Packit Service 97d2fb
    case DW_OP_div:
Packit Service 97d2fb
    case DW_OP_minus:
Packit Service 97d2fb
    case DW_OP_mod:
Packit Service 97d2fb
    case DW_OP_mul:
Packit Service 97d2fb
    case DW_OP_neg:
Packit Service 97d2fb
    case DW_OP_not:
Packit Service 97d2fb
    case DW_OP_or:
Packit Service 97d2fb
    case DW_OP_plus:
Packit Service 97d2fb
    case DW_OP_shl:
Packit Service 97d2fb
    case DW_OP_shr:
Packit Service 97d2fb
    case DW_OP_shra:
Packit Service 97d2fb
    case DW_OP_xor:
Packit Service 97d2fb
    case DW_OP_eq:
Packit Service 97d2fb
    case DW_OP_ge:
Packit Service 97d2fb
    case DW_OP_gt:
Packit Service 97d2fb
    case DW_OP_le:
Packit Service 97d2fb
    case DW_OP_lt:
Packit Service 97d2fb
    case DW_OP_ne:
Packit Service 97d2fb
    case DW_OP_lit0 ... DW_OP_lit31:
Packit Service 97d2fb
    case DW_OP_reg0 ... DW_OP_reg31:
Packit Service 97d2fb
    case DW_OP_nop:
Packit Service 97d2fb
    case DW_OP_stack_value:
Packit Service 97d2fb
      /* No arguments. */
Packit Service 97d2fb
      printf ("%s", opname);
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_form_tls_address:
Packit Service 97d2fb
      /* No arguments. Special. Pops an address and pushes the
Packit Service 97d2fb
	 corresponding address in the current thread local
Packit Service 97d2fb
	 storage. Uses the thread local storage block of the defining
Packit Service 97d2fb
	 module (executable, shared library). */
Packit Service 97d2fb
      printf ("%s", opname);
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_GNU_push_tls_address:
Packit Service 97d2fb
      /* No arguments. Special. Not the same as DW_OP_form_tls_address.
Packit Service 97d2fb
	 Pops an offset into the current thread local strorage and
Packit Service 97d2fb
	 pushes back the actual address. */
Packit Service 97d2fb
      printf ("%s", opname);
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_call_frame_cfa:
Packit Service 97d2fb
      /* No arguments. Special. Pushes Call Frame Address as computed
Packit Service 97d2fb
	 by CFI data (dwarf_cfi_addrframe will fetch that info (either from
Packit Service 97d2fb
	 the .eh_frame or .debug_frame CFI) and dwarf_frame_cfa translatesr
Packit Service 97d2fb
         the CFI instructions into a plain DWARF expression.
Packit Service 97d2fb
	 Never used in CFI itself. */
Packit Service 97d2fb
Packit Service 97d2fb
      if (attr == NULL)
Packit Service 97d2fb
	error (EXIT_FAILURE, 0, "%s used in CFI", opname);
Packit Service 97d2fb
Packit Service 97d2fb
      printf ("%s ", opname);
Packit Service 97d2fb
      if (cfi_eh == NULL && cfi_debug == NULL && !is_debug)
Packit Service 97d2fb
	error (EXIT_FAILURE, 0, "DW_OP_call_frame_cfa used but no cfi found.");
Packit Service 97d2fb
Packit Service 97d2fb
      Dwarf_Frame *frame;
Packit Service 97d2fb
      if (dwarf_cfi_addrframe (cfi_eh, addr + cfi_eh_bias, &frame) == 0
Packit Service 97d2fb
	  || dwarf_cfi_addrframe (cfi_debug, addr + cfi_debug_bias,
Packit Service 97d2fb
				  &frame) == 0)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  Dwarf_Op *cfa_ops;
Packit Service 97d2fb
	  size_t cfa_nops;
Packit Service 97d2fb
	  if (dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops) != 0)
Packit Service 97d2fb
	    error (EXIT_FAILURE, 0, "dwarf_frame_cfa 0x%" PRIx64 ": %s",
Packit Service 97d2fb
		   addr, dwarf_errmsg (-1));
Packit Service 97d2fb
	  if (cfa_nops < 1)
Packit Service 97d2fb
	    error (EXIT_FAILURE, 0, "dwarf_frame_cfa no ops");
Packit Service 97d2fb
	  print_expr_block (NULL, cfa_ops, cfa_nops, 0, depth);
Packit Service 97d2fb
	  free (frame);
Packit Service 97d2fb
	}
Packit Service 97d2fb
      else if (is_ET_REL || is_debug)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  /* XXX In ET_REL files there might be an .eh_frame with relocations
Packit Service 97d2fb
	     we don't handle (e.g. X86_64_PC32). Maybe we should?  */
Packit Service 97d2fb
	  printf ("{...}");
Packit Service 97d2fb
	}
Packit Service 97d2fb
      else
Packit Service 97d2fb
	error (EXIT_FAILURE, 0, "dwarf_cfi_addrframe 0x%" PRIx64 ": %s",
Packit Service 97d2fb
	       addr, dwarf_errmsg (-1));
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_push_object_address:
Packit Service 97d2fb
      /* No arguments. Special. Pushes object address explicitly.
Packit Service 97d2fb
       Normally only done implicitly by DW_AT_data_member_location.
Packit Service 97d2fb
       Never used in CFI. */
Packit Service 97d2fb
      if (attr == NULL)
Packit Service 97d2fb
	error (EXIT_FAILURE, 0, "%s used in CFI", opname);
Packit Service 97d2fb
      printf ("%s", opname);
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_addr:
Packit Service 97d2fb
      /* 1 address argument. */
Packit Service 97d2fb
      printf ("%s(0x%" PRIx64 ")", opname, (Dwarf_Addr) expr->number);
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_const1u:
Packit Service 97d2fb
    case DW_OP_const2u:
Packit Service 97d2fb
    case DW_OP_const4u:
Packit Service 97d2fb
    case DW_OP_const8u:
Packit Service 97d2fb
    case DW_OP_constu:
Packit Service 97d2fb
    case DW_OP_pick:
Packit Service 97d2fb
    case DW_OP_plus_uconst:
Packit Service 97d2fb
    case DW_OP_regx:
Packit Service 97d2fb
    case DW_OP_piece:
Packit Service 97d2fb
    case DW_OP_deref_size:
Packit Service 97d2fb
    case DW_OP_xderef_size:
Packit Service 97d2fb
      /* 1 numeric unsigned argument. */
Packit Service 97d2fb
      printf ("%s(%" PRIu64 ")", opname, expr->number);
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_call2:
Packit Service 97d2fb
    case DW_OP_call4:
Packit Service 97d2fb
    case DW_OP_call_ref:
Packit Service 97d2fb
      /* 1 DIE offset argument for more ops in location attribute of DIE.
Packit Service 97d2fb
         Never used in CFI.  */
Packit Service 97d2fb
      {
Packit Service 97d2fb
	if (attr == NULL)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "%s used in CFI", opname);
Packit Service 97d2fb
Packit Service 97d2fb
	Dwarf_Attribute call_attr;
Packit Service 97d2fb
	if (dwarf_getlocation_attr (attr, expr, &call_attr) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for %s error %s",
Packit Service 97d2fb
		 opname, dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	Dwarf_Die call_die;
Packit Service 97d2fb
	if (dwarf_getlocation_die (attr, expr, &call_die) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die for %s error %s",
Packit Service 97d2fb
		 opname, dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	Dwarf_Op *call_ops;
Packit Service 97d2fb
	size_t call_len;
Packit Service 97d2fb
	if (dwarf_getlocation (&call_attr, &call_ops, &call_len) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation for entry: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	printf ("%s([%" PRIx64 "]) ", opname, dwarf_dieoffset (&call_die));
Packit Service 97d2fb
	print_expr_block (&call_attr, call_ops, call_len, addr, depth);
Packit Service 97d2fb
      }
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_const1s:
Packit Service 97d2fb
    case DW_OP_const2s:
Packit Service 97d2fb
    case DW_OP_const4s:
Packit Service 97d2fb
    case DW_OP_const8s:
Packit Service 97d2fb
    case DW_OP_consts:
Packit Service 97d2fb
    case DW_OP_skip:
Packit Service 97d2fb
    case DW_OP_bra:
Packit Service 97d2fb
    case DW_OP_breg0 ... DW_OP_breg31:
Packit Service 97d2fb
      /* 1 numeric signed argument. */
Packit Service 97d2fb
      printf ("%s(%" PRId64 ")", opname, (Dwarf_Sword) expr->number);
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_fbreg:
Packit Service 97d2fb
      /* 1 numeric signed argument. Offset from frame base. */
Packit Service 97d2fb
      if (attr == NULL)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "%s used in CFI", opname);
Packit Service 97d2fb
Packit Service 97d2fb
      if (! has_frame_base)
Packit Service 97d2fb
	error (EXIT_FAILURE, 0, "DW_OP_fbreg used without a frame base");
Packit Service 97d2fb
Packit Service 97d2fb
      printf ("%s(%" PRId64 ")", opname, (Dwarf_Sword) expr->number);
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_bregx:
Packit Service 97d2fb
      /* 2 arguments, unsigned register number, signed offset. */
Packit Service 97d2fb
      printf ("%s(%" PRIu64 ",%" PRId64 ")", opname,
Packit Service 97d2fb
	      expr->number, (Dwarf_Sword) expr->number2);
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_bit_piece:
Packit Service 97d2fb
      /* 2 arguments, unsigned size, unsigned offset. */
Packit Service 97d2fb
      printf ("%s(%" PRIu64 ",%" PRIu64 ")", opname,
Packit Service 97d2fb
	      expr->number, expr->number2);
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_implicit_value:
Packit Service 97d2fb
      /* Special, unsigned size plus block. */
Packit Service 97d2fb
      {
Packit Service 97d2fb
	Dwarf_Attribute const_attr;
Packit Service 97d2fb
	Dwarf_Block block;
Packit Service 97d2fb
	if (dwarf_getlocation_attr (attr, expr, &const_attr) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	if (dwarf_formblock (&const_attr, &block) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_formblock: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	/* This is the "old" way. Check they result in the same.  */
Packit Service 97d2fb
	Dwarf_Block block_impl;
Packit Service 97d2fb
	if (dwarf_getlocation_implicit_value (attr, expr, &block_impl) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation_implicit_value: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	assert (expr->number == block.length);
Packit Service 97d2fb
	assert (block.length == block_impl.length);
Packit Service 97d2fb
	printf ("%s(%" PRIu64 "){", opname, block.length);
Packit Service 97d2fb
	for (size_t i = 0; i < block.length; i++)
Packit Service 97d2fb
	  {
Packit Service 97d2fb
	    printf ("%02x", block.data[i]);
Packit Service 97d2fb
	    assert (block.data[i] == block_impl.data[i]);
Packit Service 97d2fb
	  }
Packit Service 97d2fb
	printf("}");
Packit Service 97d2fb
      }
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_implicit_pointer:
Packit Service 97d2fb
    case DW_OP_GNU_implicit_pointer:
Packit Service 97d2fb
      /* Special, DIE offset, signed offset. Referenced DIE has a
Packit Service 97d2fb
	 location or const_value attribute. */
Packit Service 97d2fb
      {
Packit Service 97d2fb
	if (attr == NULL)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "%s used in CFI", opname);
Packit Service 97d2fb
Packit Service 97d2fb
	Dwarf_Attribute attrval;
Packit Service 97d2fb
	if (dwarf_getlocation_implicit_pointer (attr, expr, &attrval) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation_implicit_pointer: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	// Sanity check, results should be the same.
Packit Service 97d2fb
	Dwarf_Attribute attrval2;
Packit Service 97d2fb
	if (dwarf_getlocation_attr (attr, expr, &attrval2) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	assert (dwarf_whatattr (&attrval) == dwarf_whatattr (&attrval2));
Packit Service 97d2fb
	assert (dwarf_whatform (&attrval) == dwarf_whatform (&attrval2));
Packit Service 97d2fb
	// In theory two different valp pointers could point to the same
Packit Service 97d2fb
	// value. But here we really expect them to be the equal.
Packit Service 97d2fb
	assert (attrval.valp == attrval2.valp);
Packit Service 97d2fb
Packit Service 97d2fb
	Dwarf_Die impl_die;
Packit Service 97d2fb
	if (dwarf_getlocation_die (attr, expr, &impl_die) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	printf ("%s([%" PRIx64 "],%" PRId64 ") ", opname,
Packit Service 97d2fb
		dwarf_dieoffset (&impl_die), expr->number2);
Packit Service 97d2fb
Packit Service 97d2fb
	if (dwarf_whatattr (&attrval) == DW_AT_const_value)
Packit Service 97d2fb
	  printf ("<constant value>"); // Lookup type...
Packit Service 97d2fb
	else
Packit Service 97d2fb
	  {
Packit Service 97d2fb
	    // Lookup the location description at the current address.
Packit Service 97d2fb
	    Dwarf_Op *exprval;
Packit Service 97d2fb
	    size_t exprval_len;
Packit Service 97d2fb
	    int locs = dwarf_getlocation_addr (&attrval, addr,
Packit Service 97d2fb
					       &exprval, &exprval_len, 1);
Packit Service 97d2fb
	    if (locs == 0)
Packit Service 97d2fb
	      printf ("<no location>"); // This means "optimized out".
Packit Service 97d2fb
	    else if (locs == 1)
Packit Service 97d2fb
	      print_expr_block (&attrval, exprval, exprval_len, addr, depth);
Packit Service 97d2fb
	    else
Packit Service 97d2fb
	      error (EXIT_FAILURE, 0,
Packit Service 97d2fb
		     "dwarf_getlocation_addr attrval at addr 0x%" PRIx64
Packit Service 97d2fb
		     ", locs (%d): %s", addr, locs, dwarf_errmsg (-1));
Packit Service 97d2fb
	  }
Packit Service 97d2fb
      }
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_GNU_variable_value:
Packit Service 97d2fb
      /* Special, DIE offset. Referenced DIE has a location or const_value
Packit Service 97d2fb
	 attribute. */
Packit Service 97d2fb
      {
Packit Service 97d2fb
	if (attr == NULL)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "%s used in CFI", opname);
Packit Service 97d2fb
Packit Service 97d2fb
	Dwarf_Attribute attrval;
Packit Service 97d2fb
	if (dwarf_getlocation_attr (attr, expr, &attrval) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	Dwarf_Die impl_die;
Packit Service 97d2fb
	if (dwarf_getlocation_die (attr, expr, &impl_die) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	printf ("%s([%" PRIx64 "]) ", opname, dwarf_dieoffset (&impl_die));
Packit Service 97d2fb
Packit Service 97d2fb
	if (dwarf_whatattr (&attrval) == DW_AT_const_value)
Packit Service 97d2fb
	  printf ("<constant value>"); // Lookup type...
Packit Service 97d2fb
	else
Packit Service 97d2fb
	  {
Packit Service 97d2fb
	    // Lookup the location description at the current address.
Packit Service 97d2fb
	    Dwarf_Op *exprval;
Packit Service 97d2fb
	    size_t exprval_len;
Packit Service 97d2fb
	    int locs = dwarf_getlocation_addr (&attrval, addr,
Packit Service 97d2fb
					       &exprval, &exprval_len, 1);
Packit Service 97d2fb
	    if (locs == 0)
Packit Service 97d2fb
	      printf ("<no location>"); // This means "optimized out".
Packit Service 97d2fb
	    else if (locs == 1)
Packit Service 97d2fb
	      print_expr_block (&attrval, exprval, exprval_len, addr, depth);
Packit Service 97d2fb
	    else
Packit Service 97d2fb
	      error (EXIT_FAILURE, 0,
Packit Service 97d2fb
		     "dwarf_getlocation_addr attrval at addr 0x%" PRIx64
Packit Service 97d2fb
		     ", locs (%d): %s", addr, locs, dwarf_errmsg (-1));
Packit Service 97d2fb
	  }
Packit Service 97d2fb
      }
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_entry_value:
Packit Service 97d2fb
    case DW_OP_GNU_entry_value:
Packit Service 97d2fb
      /* Special, unsigned size plus expression block. All registers
Packit Service 97d2fb
	 inside the block should be interpreted as they had on
Packit Service 97d2fb
	 entering the function. dwarf_getlocation_attr will return an
Packit Service 97d2fb
	 attribute containing the block as locexpr which can be
Packit Service 97d2fb
	 retrieved with dwarf_getlocation.  */
Packit Service 97d2fb
      {
Packit Service 97d2fb
	Dwarf_Attribute entry_attr;
Packit Service 97d2fb
	if (dwarf_getlocation_attr (attr, expr, &entry_attr) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	Dwarf_Op *entry_ops;
Packit Service 97d2fb
	size_t entry_len;
Packit Service 97d2fb
	if (dwarf_getlocation (&entry_attr, &entry_ops, &entry_len) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation for entry: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	printf ("%s(%zd) ", opname, entry_len);
Packit Service 97d2fb
	print_expr_block (attr, entry_ops, entry_len, addr, depth);
Packit Service 97d2fb
      }
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_GNU_parameter_ref:
Packit Service 97d2fb
      /* Special, unsigned CU relative DIE offset pointing to a
Packit Service 97d2fb
	 DW_TAG_formal_parameter. The value that parameter had at the
Packit Service 97d2fb
	 call site of the current function will be put on the DWARF
Packit Service 97d2fb
	 stack. The value can be retrieved by finding the
Packit Service 97d2fb
	 DW_TAG_GNU_call_site_parameter which has as
Packit Service 97d2fb
	 DW_AT_abstract_origin the same formal parameter DIE. */
Packit Service 97d2fb
      {
Packit Service 97d2fb
	Dwarf_Die param;
Packit Service 97d2fb
	if (dwarf_getlocation_die (attr, expr, &param) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
	// XXX actually lookup DW_TAG_GNU_call_site_parameter
Packit Service 97d2fb
	printf ("%s[%" PRIx64 "]", opname, dwarf_dieoffset (&param));
Packit Service 97d2fb
	assert (expr->number == dwarf_cuoffset (&param));
Packit Service 97d2fb
	if (dwarf_tag (&param) != DW_TAG_formal_parameter)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "Not a formal parameter");
Packit Service 97d2fb
      }
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_convert:
Packit Service 97d2fb
    case DW_OP_GNU_convert:
Packit Service 97d2fb
    case DW_OP_reinterpret:
Packit Service 97d2fb
    case DW_OP_GNU_reinterpret:
Packit Service 97d2fb
      /* Special, unsigned CU relative DIE offset pointing to a
Packit Service 97d2fb
	 DW_TAG_base_type. Pops a value, converts or reinterprets the
Packit Service 97d2fb
	 value to the given type. When the argument is zero the value
Packit Service 97d2fb
	 becomes untyped again. */
Packit Service 97d2fb
      {
Packit Service 97d2fb
	Dwarf_Die type;
Packit Service 97d2fb
	Dwarf_Off off = expr->number;
Packit Service 97d2fb
	if (off != 0)
Packit Service 97d2fb
	  {
Packit Service 97d2fb
	    if (dwarf_getlocation_die (attr, expr, &type) != 0)
Packit Service 97d2fb
	      error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
Packit Service 97d2fb
		     dwarf_errmsg (-1));
Packit Service 97d2fb
	    off = dwarf_dieoffset (&type);
Packit Service 97d2fb
	    assert (expr->number == dwarf_cuoffset (&type));
Packit Service 97d2fb
	    printf ("%s", opname);
Packit Service 97d2fb
	    print_base_type (&type);
Packit Service 97d2fb
	  }
Packit Service 97d2fb
	else
Packit Service 97d2fb
	  printf ("%s[%" PRIu64 "]", opname, off);
Packit Service 97d2fb
Packit Service 97d2fb
      }
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_regval_type:
Packit Service 97d2fb
    case DW_OP_GNU_regval_type:
Packit Service 97d2fb
      /* Special, unsigned register number plus unsigned CU relative
Packit Service 97d2fb
         DIE offset pointing to a DW_TAG_base_type. */
Packit Service 97d2fb
      {
Packit Service 97d2fb
	Dwarf_Die type;
Packit Service 97d2fb
	if (dwarf_getlocation_die (attr, expr, &type) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
	assert (expr->number2 == dwarf_cuoffset (&type));
Packit Service 97d2fb
	// XXX check size against base_type size?
Packit Service 97d2fb
	printf ("%s(reg%" PRIu64 ")", opname, expr->number);
Packit Service 97d2fb
	print_base_type (&type);
Packit Service 97d2fb
      }
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_deref_type:
Packit Service 97d2fb
    case DW_OP_GNU_deref_type:
Packit Service 97d2fb
      /* Special, unsigned size plus unsigned CU relative DIE offset
Packit Service 97d2fb
	 pointing to a DW_TAG_base_type. */
Packit Service 97d2fb
      {
Packit Service 97d2fb
	Dwarf_Die type;
Packit Service 97d2fb
	if (dwarf_getlocation_die (attr, expr, &type) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
	assert (expr->number2 == dwarf_cuoffset (&type));
Packit Service 97d2fb
	// XXX check size against base_type size?
Packit Service 97d2fb
	printf ("%s(%" PRIu64 ")", opname, expr->number);
Packit Service 97d2fb
	print_base_type (&type);
Packit Service 97d2fb
      }
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_xderef_type:
Packit Service 97d2fb
      /* Special, unsigned size plus unsigned DIE offset
Packit Service 97d2fb
	 pointing to a DW_TAG_base_type. */
Packit Service 97d2fb
      {
Packit Service 97d2fb
	Dwarf_Die type;
Packit Service 97d2fb
	if (dwarf_getlocation_die (attr, expr, &type) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
	// XXX check size against base_type size?
Packit Service 97d2fb
	printf ("%s(%" PRIu64 ")", opname, expr->number);
Packit Service 97d2fb
	print_base_type (&type);
Packit Service 97d2fb
      }
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_const_type:
Packit Service 97d2fb
    case DW_OP_GNU_const_type:
Packit Service 97d2fb
      /* Special, unsigned CU relative DIE offset pointing to a
Packit Service 97d2fb
	 DW_TAG_base_type, an unsigned size length plus a block with
Packit Service 97d2fb
	 the constant value. */
Packit Service 97d2fb
      {
Packit Service 97d2fb
	Dwarf_Die type;
Packit Service 97d2fb
	if (dwarf_getlocation_die (attr, expr, &type) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
	assert (expr->number == dwarf_cuoffset (&type));
Packit Service 97d2fb
Packit Service 97d2fb
	Dwarf_Attribute const_attr;
Packit Service 97d2fb
	if (dwarf_getlocation_attr (attr, expr, &const_attr) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for type: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
	  
Packit Service 97d2fb
	Dwarf_Block block;
Packit Service 97d2fb
	if (dwarf_formblock (&const_attr, &block) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_formblock for type: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	printf ("%s", opname);
Packit Service 97d2fb
	print_base_type (&type);
Packit Service 97d2fb
	printf ("(%" PRIu64 ")[", block.length);
Packit Service 97d2fb
	for (size_t i = 0; i < block.length; i++)
Packit Service 97d2fb
	  printf ("%02x", block.data[i]);
Packit Service 97d2fb
	printf("]");
Packit Service 97d2fb
      }
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_GNU_addr_index:
Packit Service 97d2fb
    case DW_OP_addrx:
Packit Service 97d2fb
      /* Address from the .debug_addr section (indexed based on CU).  */
Packit Service 97d2fb
      {
Packit Service 97d2fb
	Dwarf_Attribute addr_attr;
Packit Service 97d2fb
	if (dwarf_getlocation_attr (attr, expr, &addr_attr) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for addr: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	Dwarf_Addr address;
Packit Service 97d2fb
	if (dwarf_formaddr (&addr_attr, &address) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_formaddr address failed: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	printf ("addr: 0x%" PRIx64, address);
Packit Service 97d2fb
      }
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case DW_OP_GNU_const_index:
Packit Service 97d2fb
    case DW_OP_constx:
Packit Service 97d2fb
      /* Constant from the .debug_addr section (indexed based on CU).  */
Packit Service 97d2fb
      {
Packit Service 97d2fb
	Dwarf_Attribute addr_attr;
Packit Service 97d2fb
	if (dwarf_getlocation_attr (attr, expr, &addr_attr) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for addr: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	Dwarf_Word constant;
Packit Service 97d2fb
	if (dwarf_formudata (&addr_attr, &constant) != 0)
Packit Service 97d2fb
	  error (EXIT_FAILURE, 0, "dwarf_formudata constant failed: %s",
Packit Service 97d2fb
		 dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	printf ("const: 0x%" PRIx64, constant);
Packit Service 97d2fb
      }
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    default:
Packit Service 97d2fb
      error (EXIT_FAILURE, 0, "unhandled opcode: DW_OP_%s (0x%x)",
Packit Service 97d2fb
	     opname, atom);
Packit Service 97d2fb
    }
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
/* Get all variables and print their value expressions. */
Packit Service 97d2fb
static void
Packit Service 97d2fb
print_varlocs (Dwarf_Die *funcdie)
Packit Service 97d2fb
{
Packit Service 97d2fb
  // Display frame base for function if it exists.
Packit Service 97d2fb
  // Should be used for DW_OP_fbreg.
Packit Service 97d2fb
  has_frame_base = dwarf_hasattr (funcdie, DW_AT_frame_base);
Packit Service 97d2fb
  if (has_frame_base)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      Dwarf_Attribute fb_attr;
Packit Service 97d2fb
      if (dwarf_attr (funcdie, DW_AT_frame_base, &fb_attr) == NULL)
Packit Service 97d2fb
	error (EXIT_FAILURE, 0, "dwarf_attr fb: %s", dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
      Dwarf_Op *fb_expr;
Packit Service 97d2fb
      size_t fb_exprlen;
Packit Service 97d2fb
      if (dwarf_getlocation (&fb_attr, &fb_expr, &fb_exprlen) == 0)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  // Covers all of function.
Packit Service 97d2fb
	  Dwarf_Addr entrypc;
Packit Service 97d2fb
	  if (dwarf_entrypc (funcdie, &entrypc) != 0)
Packit Service 97d2fb
	    error (EXIT_FAILURE, 0, "dwarf_entrypc: %s", dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	  printf ("    frame_base: ");
Packit Service 97d2fb
	  if (entrypc == 0)
Packit Service 97d2fb
	    printf ("XXX zero address"); // XXX bad DWARF?
Packit Service 97d2fb
	  else
Packit Service 97d2fb
	    print_expr_block (&fb_attr, fb_expr, fb_exprlen, entrypc, 0);
Packit Service 97d2fb
	  printf ("\n");
Packit Service 97d2fb
	}
Packit Service 97d2fb
      else
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  Dwarf_Addr base, start, end;
Packit Service 97d2fb
	  ptrdiff_t off = 0;
Packit Service 97d2fb
	  printf ("    frame_base:\n");
Packit Service 97d2fb
          while ((off = dwarf_getlocations (&fb_attr, off, &base,
Packit Service 97d2fb
					    &start, &end,
Packit Service 97d2fb
					    &fb_expr, &fb_exprlen)) > 0)
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      printf ("      (%" PRIx64 ",%" PRIx64 ") ", start, end);
Packit Service 97d2fb
	      print_expr_block (&fb_attr, fb_expr, fb_exprlen, start, 0);
Packit Service 97d2fb
	      printf ("\n");
Packit Service 97d2fb
	    }
Packit Service 97d2fb
Packit Service 97d2fb
	  if (off < 0)
Packit Service 97d2fb
	    error (EXIT_FAILURE, 0, "dwarf_getlocations fb: %s",
Packit Service 97d2fb
		   dwarf_errmsg (-1));
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
  else if (dwarf_tag (funcdie) == DW_TAG_inlined_subroutine)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      // See whether the subprogram we are inlined into has a frame
Packit Service 97d2fb
      // base we should use.
Packit Service 97d2fb
      Dwarf_Die *scopes;
Packit Service 97d2fb
      int n = dwarf_getscopes_die (funcdie, &scopes);
Packit Service 97d2fb
      if (n <= 0)
Packit Service 97d2fb
	error (EXIT_FAILURE, 0, "dwarf_getscopes_die: %s", dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
      while (n-- > 0)
Packit Service 97d2fb
	if (dwarf_tag (&scopes[n]) == DW_TAG_subprogram
Packit Service 97d2fb
	    && dwarf_hasattr (&scopes[n], DW_AT_frame_base))
Packit Service 97d2fb
	  {
Packit Service 97d2fb
	    has_frame_base = true;
Packit Service 97d2fb
	    break;
Packit Service 97d2fb
	  }
Packit Service 97d2fb
      free (scopes);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  if (! dwarf_haschildren (funcdie))
Packit Service 97d2fb
    return;
Packit Service 97d2fb
Packit Service 97d2fb
  Dwarf_Die child;
Packit Service 97d2fb
  int res = dwarf_child (funcdie, &child);
Packit Service 97d2fb
  if (res < 0)
Packit Service 97d2fb
    error (EXIT_FAILURE, 0, "dwarf_child: %s", dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
  /* We thought there was a child, but the child list was actually
Packit Service 97d2fb
     empty. This isn't technically an error in the DWARF, but it is
Packit Service 97d2fb
     certainly non-optimimal.  */
Packit Service 97d2fb
  if (res == 1)
Packit Service 97d2fb
    return;
Packit Service 97d2fb
Packit Service 97d2fb
  do
Packit Service 97d2fb
    {
Packit Service 97d2fb
      int tag = dwarf_tag (&child);
Packit Service 97d2fb
      if (tag == DW_TAG_variable || tag == DW_TAG_formal_parameter)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  const char *what = tag == DW_TAG_variable ? "variable" : "parameter";
Packit Service 97d2fb
	  print_die (&child, what, 2);
Packit Service 97d2fb
Packit Service 97d2fb
	  if (dwarf_hasattr (&child, DW_AT_location))
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      Dwarf_Attribute attr;
Packit Service 97d2fb
	      if (dwarf_attr (&child, DW_AT_location, &attr) == NULL)
Packit Service 97d2fb
		error (EXIT_FAILURE, 0, "dwarf_attr: %s", dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	      Dwarf_Op *expr;
Packit Service 97d2fb
	      size_t exprlen;
Packit Service 97d2fb
	      if (dwarf_getlocation (&attr, &expr, &exprlen) == 0)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  // Covers all ranges of the function.
Packit Service 97d2fb
		  // Evaluate the expression block for each range.
Packit Service 97d2fb
		  ptrdiff_t offset = 0;
Packit Service 97d2fb
		  Dwarf_Addr base, begin, end;
Packit Service 97d2fb
		  do
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      offset = dwarf_ranges (funcdie, offset, &base,
Packit Service 97d2fb
					     &begin, &end;;
Packit Service 97d2fb
		      if (offset < 0)
Packit Service 97d2fb
			error (EXIT_FAILURE, 0, "dwarf_ranges: %s",
Packit Service 97d2fb
			       dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
		      if (offset > 0)
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  if (exprlen == 0)
Packit Service 97d2fb
			    printf ("      (%"
Packit Service 97d2fb
				    PRIx64 ",%" PRIx64
Packit Service 97d2fb
				    ") <empty expression>\n", begin, end);
Packit Service 97d2fb
			  else
Packit Service 97d2fb
			    print_expr_block_addrs (&attr, begin, end,
Packit Service 97d2fb
						    expr, exprlen);
Packit Service 97d2fb
			}
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  while (offset > 0);
Packit Service 97d2fb
Packit Service 97d2fb
		  if (offset < 0)
Packit Service 97d2fb
		    error (EXIT_FAILURE, 0, "dwarf_ranges: %s",
Packit Service 97d2fb
			   dwarf_errmsg (-1));
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  Dwarf_Addr base, begin, end;
Packit Service 97d2fb
		  ptrdiff_t offset = 0;
Packit Service 97d2fb
		  while ((offset = dwarf_getlocations (&attr, offset,
Packit Service 97d2fb
						       &base, &begin, &end,
Packit Service 97d2fb
						       &expr, &exprlen)) > 0)
Packit Service 97d2fb
		    if (begin >= end)
Packit Service 97d2fb
		      printf ("      (%" PRIx64 ",%" PRIx64
Packit Service 97d2fb
			      ") <empty range>\n", begin, end); // XXX report?
Packit Service 97d2fb
		    else
Packit Service 97d2fb
		      {
Packit Service 97d2fb
			print_expr_block_addrs (&attr, begin, end,
Packit Service 97d2fb
						expr, exprlen);
Packit Service 97d2fb
Packit Service 97d2fb
			// Extra sanity check for dwarf_getlocation_addr
Packit Service 97d2fb
			// Must at least find one range for begin and end-1.
Packit Service 97d2fb
			Dwarf_Op *expraddr;
Packit Service 97d2fb
			size_t expraddr_len;
Packit Service 97d2fb
			int locs = dwarf_getlocation_addr (&attr, begin,
Packit Service 97d2fb
							   &expraddr,
Packit Service 97d2fb
							   &expraddr_len, 1);
Packit Service 97d2fb
			assert (locs == 1);
Packit Service 97d2fb
			locs = dwarf_getlocation_addr (&attr, end - 1,
Packit Service 97d2fb
						       &expraddr,
Packit Service 97d2fb
						       &expraddr_len, 1);
Packit Service 97d2fb
			assert (locs == 1);
Packit Service 97d2fb
		      }
Packit Service 97d2fb
Packit Service 97d2fb
		  if (offset < 0)
Packit Service 97d2fb
		    error (EXIT_FAILURE, 0, "dwarf_getlocations: %s",
Packit Service 97d2fb
			   dwarf_errmsg (-1));
Packit Service 97d2fb
		}
Packit Service 97d2fb
	    }
Packit Service 97d2fb
	  else if (dwarf_hasattr (&child, DW_AT_const_value))
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      printf ("      <constant value>\n"); // Lookup type and print.
Packit Service 97d2fb
	    }
Packit Service 97d2fb
	  else
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      printf ("      <no value>\n");
Packit Service 97d2fb
	    }
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
  while (dwarf_siblingof (&child, &child) == 0);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static int
Packit Service 97d2fb
handle_instance (Dwarf_Die *funcdie, void *arg __attribute__ ((unused)))
Packit Service 97d2fb
{
Packit Service 97d2fb
  print_die (funcdie, "inlined function", 1);
Packit Service 97d2fb
  print_varlocs (funcdie);
Packit Service 97d2fb
Packit Service 97d2fb
  return DWARF_CB_OK;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static int
Packit Service 97d2fb
handle_function (Dwarf_Die *funcdie, void *arg __attribute__((unused)))
Packit Service 97d2fb
{
Packit Service 97d2fb
  if (dwarf_func_inline (funcdie) > 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      // abstract inline definition, find all inlined instances.
Packit Service 97d2fb
Packit Service 97d2fb
      // Note this is convenient for listing all instances together
Packit Service 97d2fb
      // so you can easily compare the location expressions describing
Packit Service 97d2fb
      // the variables and parameters, but it isn't very efficient
Packit Service 97d2fb
      // since it will walk the DIE tree multiple times.
Packit Service 97d2fb
      if (dwarf_func_inline_instances (funcdie, &handle_instance, NULL) != 0)
Packit Service 97d2fb
	error (EXIT_FAILURE, 0, "dwarf_func_inline_instances: %s",
Packit Service 97d2fb
	       dwarf_errmsg (-1));
Packit Service 97d2fb
    }
Packit Service 97d2fb
  else
Packit Service 97d2fb
    {
Packit Service 97d2fb
      // Contains actual code, not just a declaration?
Packit Service 97d2fb
      Dwarf_Addr entrypc;
Packit Service 97d2fb
      if (dwarf_entrypc (funcdie, &entrypc) == 0)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  print_die (funcdie, "function", 1);
Packit Service 97d2fb
	  print_varlocs (funcdie);
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  return DWARF_CB_OK;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
struct attr_arg
Packit Service 97d2fb
{
Packit Service 97d2fb
  int depth;
Packit Service 97d2fb
  Dwarf_Addr entrypc;
Packit Service 97d2fb
};
Packit Service 97d2fb
Packit Service 97d2fb
static int
Packit Service 97d2fb
handle_attr (Dwarf_Attribute *attr, void *arg)
Packit Service 97d2fb
{
Packit Service 97d2fb
  int depth = ((struct attr_arg *) arg)->depth;
Packit Service 97d2fb
  Dwarf_Addr entrypc = ((struct attr_arg *) arg)->entrypc;
Packit Service 97d2fb
Packit Service 97d2fb
  unsigned int code = dwarf_whatattr (attr);
Packit Service 97d2fb
  unsigned int form = dwarf_whatform (attr);
Packit Service 97d2fb
Packit Service 97d2fb
  printf ("%*s%s (%s)", depth * 2, "",
Packit Service 97d2fb
	  dwarf_attr_string (code), dwarf_form_string (form));
Packit Service 97d2fb
Packit Service 97d2fb
  /* If we can get an DWARF expression (or location lists) from this
Packit Service 97d2fb
     attribute we'll print it, otherwise we'll ignore it.  But if
Packit Service 97d2fb
     there is an error while the attribute has the "correct" form then
Packit Service 97d2fb
     we'll report an error (we can only really check DW_FORM_exprloc
Packit Service 97d2fb
     other forms can be ambiguous).  */
Packit Service 97d2fb
  Dwarf_Op *expr;
Packit Service 97d2fb
  size_t exprlen;
Packit Service 97d2fb
  bool printed = false;
Packit Service 97d2fb
  int res = dwarf_getlocation (attr, &expr, &exprlen);
Packit Service 97d2fb
  if (res == 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf (" ");
Packit Service 97d2fb
      print_expr_block (attr, expr, exprlen, entrypc, 0);
Packit Service 97d2fb
      printf ("\n");
Packit Service 97d2fb
      printed = true;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  else if (form == DW_FORM_exprloc)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      error (0, 0, "%s dwarf_getlocation failed: %s",
Packit Service 97d2fb
	     dwarf_attr_string (code), dwarf_errmsg (-1));
Packit Service 97d2fb
      return DWARF_CB_ABORT;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  else
Packit Service 97d2fb
    {
Packit Service 97d2fb
      Dwarf_Addr base, begin, end;
Packit Service 97d2fb
      ptrdiff_t offset = 0;
Packit Service 97d2fb
      while ((offset = dwarf_getlocations (attr, offset,
Packit Service 97d2fb
					   &base, &begin, &end,
Packit Service 97d2fb
					   &expr, &exprlen)) > 0)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  if (! printed)
Packit Service 97d2fb
	    printf ("\n");
Packit Service 97d2fb
	  printf ("%*s", depth * 2, "");
Packit Service 97d2fb
	  print_expr_block_addrs (attr, begin, end, expr, exprlen);
Packit Service 97d2fb
	  printed = true;
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  if (! printed)
Packit Service 97d2fb
    printf ("\n");
Packit Service 97d2fb
Packit Service 97d2fb
  return DWARF_CB_OK;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static void
Packit Service 97d2fb
handle_die (Dwarf_Die *die, int depth, bool outer_has_frame_base,
Packit Service 97d2fb
	    Dwarf_Addr outer_entrypc)
Packit Service 97d2fb
{
Packit Service 97d2fb
  /* CU DIE already printed.  */
Packit Service 97d2fb
  if (depth > 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      const char *name = dwarf_diename (die);
Packit Service 97d2fb
      if (name != NULL)
Packit Service 97d2fb
	printf ("%*s[%" PRIx64 "] %s \"%s\"\n", depth * 2, "",
Packit Service 97d2fb
		dwarf_dieoffset (die), dwarf_tag_string (dwarf_tag (die)),
Packit Service 97d2fb
		name);
Packit Service 97d2fb
      else
Packit Service 97d2fb
	printf ("%*s[%" PRIx64 "] %s\n", depth * 2, "",
Packit Service 97d2fb
		dwarf_dieoffset (die), dwarf_tag_string (dwarf_tag (die)));
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  struct attr_arg arg;
Packit Service 97d2fb
  arg.depth = depth + 1;
Packit Service 97d2fb
Packit Service 97d2fb
  /* The (lowest) address to use for (looking up) operands that depend
Packit Service 97d2fb
     on address.  */
Packit Service 97d2fb
  Dwarf_Addr die_entrypc;
Packit Service 97d2fb
  if (dwarf_entrypc (die, &die_entrypc) != 0 || die_entrypc == 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* Try to get the lowest address of the first range covered.  */
Packit Service 97d2fb
      Dwarf_Addr base, start, end;
Packit Service 97d2fb
      if (dwarf_ranges (die, 0, &base, &start, &end) <= 0 || start == 0)
Packit Service 97d2fb
	die_entrypc = outer_entrypc;
Packit Service 97d2fb
      else
Packit Service 97d2fb
	die_entrypc = start;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  arg.entrypc = die_entrypc;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Whether this or the any outer DIE has a frame base. Used as
Packit Service 97d2fb
     sanity check when printing experssions that use DW_OP_fbreg.  */
Packit Service 97d2fb
  bool die_has_frame_base = dwarf_hasattr (die, DW_AT_frame_base);
Packit Service 97d2fb
  die_has_frame_base |= outer_has_frame_base;
Packit Service 97d2fb
  has_frame_base = die_has_frame_base;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Look through all attributes to find those that contain DWARF
Packit Service 97d2fb
     expressions and print those.  We expect to handle all attributes,
Packit Service 97d2fb
     anything else is an error.  */
Packit Service 97d2fb
  if (dwarf_getattrs (die, handle_attr, &arg, 0) != 1)
Packit Service 97d2fb
    error (EXIT_FAILURE, 0, "Couldn't get all attributes: %s",
Packit Service 97d2fb
	   dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
  /* Handle children and siblings recursively depth first.  */
Packit Service 97d2fb
  Dwarf_Die child;
Packit Service 97d2fb
  if (dwarf_haschildren (die) != 0 && dwarf_child (die, &child) == 0)
Packit Service 97d2fb
    handle_die (&child, depth + 1, die_has_frame_base, die_entrypc);
Packit Service 97d2fb
Packit Service 97d2fb
  Dwarf_Die sibling;
Packit Service 97d2fb
  if (dwarf_siblingof (die, &sibling) == 0)
Packit Service 97d2fb
    handle_die (&sibling, depth, outer_has_frame_base, outer_entrypc);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
int
Packit Service 97d2fb
main (int argc, char *argv[])
Packit Service 97d2fb
{
Packit Service 97d2fb
  /* With --exprlocs we process all DIEs looking for any attribute
Packit Service 97d2fb
     which contains an DWARF expression (but not location lists) and
Packit Service 97d2fb
     print those.  Otherwise we process all function DIEs and print
Packit Service 97d2fb
     all DWARF expressions and location lists associated with
Packit Service 97d2fb
     parameters and variables). It must be the first argument,
Packit Service 97d2fb
     or the second, after --debug.  */
Packit Service 97d2fb
  bool exprlocs = false;
Packit Service 97d2fb
Packit Service 97d2fb
  /* With --debug we ignore not being able to find .eh_frame.
Packit Service 97d2fb
     It must come as first argument.  */
Packit Service 97d2fb
  is_debug = false;
Packit Service 97d2fb
  if (argc > 1)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      if (strcmp ("--exprlocs", argv[1]) == 0)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  exprlocs = true;
Packit Service 97d2fb
	  argv[1] = "";
Packit Service 97d2fb
	}
Packit Service 97d2fb
      else if (strcmp ("--debug", argv[1]) == 0)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  is_debug = true;
Packit Service 97d2fb
	  argv[1] = "";
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  if (argc > 2)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      if (strcmp ("--exprlocs", argv[2]) == 0)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  exprlocs = true;
Packit Service 97d2fb
	  argv[2] = "";
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  int remaining;
Packit Service 97d2fb
  Dwfl *dwfl;
Packit Service 97d2fb
  (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining,
Packit Service 97d2fb
                     &dwfl);
Packit Service 97d2fb
  assert (dwfl != NULL);
Packit Service 97d2fb
Packit Service 97d2fb
  Dwarf_Die *cu = NULL;
Packit Service 97d2fb
  Dwarf_Addr dwbias;
Packit Service 97d2fb
  bool found_cu = false;
Packit Service 97d2fb
  while ((cu = dwfl_nextcu (dwfl, cu, &dwbias)) != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* Only walk actual compile units (not partial units) that
Packit Service 97d2fb
	 contain code if we are only interested in the function variable
Packit Service 97d2fb
	 locations.  */
Packit Service 97d2fb
      Dwarf_Die cudie;
Packit Service 97d2fb
      Dwarf_Die subdie;
Packit Service 97d2fb
      uint8_t unit_type;
Packit Service 97d2fb
      if (dwarf_cu_info (cu->cu, NULL, &unit_type, &cudie, &subdie,
Packit Service 97d2fb
		         NULL, NULL, NULL) != 0)
Packit Service 97d2fb
	error (EXIT_FAILURE, 0, "dwarf_cu_info: %s", dwarf_errmsg (-1));
Packit Service 97d2fb
      if (unit_type == DW_UT_skeleton)
Packit Service 97d2fb
	cudie = subdie;
Packit Service 97d2fb
Packit Service 97d2fb
      Dwarf_Addr cubase;
Packit Service 97d2fb
      if (dwarf_tag (&cudie) == DW_TAG_compile_unit
Packit Service 97d2fb
	  && (exprlocs || dwarf_lowpc (&cudie, &cubase) == 0))
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  found_cu = true;
Packit Service 97d2fb
Packit Service 97d2fb
	  Dwfl_Module *mod = dwfl_cumodule (cu);
Packit Service 97d2fb
	  Dwarf_Addr modbias;
Packit Service 97d2fb
	  dw = dwfl_module_getdwarf (mod, &modbias);
Packit Service 97d2fb
	  assert (dwbias == modbias);
Packit Service 97d2fb
Packit Service 97d2fb
	  const char *mainfile;
Packit Service 97d2fb
	  const char *modname = dwfl_module_info (mod, NULL,
Packit Service 97d2fb
						  NULL, NULL,
Packit Service 97d2fb
						  NULL, NULL,
Packit Service 97d2fb
						  &mainfile,
Packit Service 97d2fb
						  NULL);
Packit Service 97d2fb
	  if (modname == NULL)
Packit Service 97d2fb
	    error (EXIT_FAILURE, 0, "dwfl_module_info: %s", dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
	  const char *name = (modname[0] != '\0'
Packit Service 97d2fb
			      ? modname
Packit Service 97d2fb
			      :  basename (mainfile));
Packit Service 97d2fb
	  printf ("module '%s'\n", name);
Packit Service 97d2fb
	  print_die (&cudie, "CU", 0);
Packit Service 97d2fb
Packit Service 97d2fb
	  Dwarf_Addr elfbias;
Packit Service 97d2fb
	  Elf *elf = dwfl_module_getelf (mod, &elfbias);
Packit Service 97d2fb
Packit Service 97d2fb
	  // CFI. We need both since sometimes neither is complete.
Packit Service 97d2fb
	  cfi_debug = dwfl_module_dwarf_cfi (mod, &cfi_debug_bias);
Packit Service 97d2fb
	  cfi_eh = dwfl_module_eh_cfi (mod, &cfi_eh_bias);
Packit Service 97d2fb
Packit Service 97d2fb
	  // No bias needed, same file.
Packit Service 97d2fb
	  assert (cfi_debug == NULL || cfi_debug_bias == 0);
Packit Service 97d2fb
Packit Service 97d2fb
	  // We are a bit forgiving for object files.  There might be
Packit Service 97d2fb
	  // relocations we don't handle that are needed in some
Packit Service 97d2fb
	  // places...
Packit Service 97d2fb
	  GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
Packit Service 97d2fb
	  is_ET_REL = ehdr->e_type == ET_REL;
Packit Service 97d2fb
Packit Service 97d2fb
	  if (exprlocs)
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      Dwarf_Addr entrypc;
Packit Service 97d2fb
	      if (dwarf_entrypc (&cudie, &entrypc) != 0)
Packit Service 97d2fb
		entrypc = 0;
Packit Service 97d2fb
Packit Service 97d2fb
	      /* XXX - Passing true for has_frame_base is not really true.
Packit Service 97d2fb
		 We do it because we want to resolve all DIEs and all
Packit Service 97d2fb
		 attributes. Technically we should check that the DIE
Packit Service 97d2fb
		 (types) are referenced from variables that are defined in
Packit Service 97d2fb
		 a context (function) that has a frame base.  */
Packit Service 97d2fb
	      handle_die (&cudie, 0, true /* Should be false */, entrypc);
Packit Service 97d2fb
	    }
Packit Service 97d2fb
	  else if (dwarf_getfuncs (&cudie, handle_function, NULL, 0) != 0)
Packit Service 97d2fb
	    error (EXIT_FAILURE, 0, "dwarf_getfuncs %s",
Packit Service 97d2fb
		   dwarf_errmsg (-1));
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  if (! found_cu)
Packit Service 97d2fb
    error (EXIT_FAILURE, 0, "No DWARF CU found?");
Packit Service 97d2fb
Packit Service 97d2fb
  dwfl_end (dwfl);
Packit Service 97d2fb
  return 0;
Packit Service 97d2fb
}