Blame libdw/libdwP.h

Packit Service 97d2fb
/* Internal definitions for libdw.
Packit Service 97d2fb
   Copyright (C) 2002-2011, 2013-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 either
Packit Service 97d2fb
Packit Service 97d2fb
     * the GNU Lesser General Public License as published by the Free
Packit Service 97d2fb
       Software Foundation; either version 3 of the License, or (at
Packit Service 97d2fb
       your option) any later version
Packit Service 97d2fb
Packit Service 97d2fb
   or
Packit Service 97d2fb
Packit Service 97d2fb
     * the GNU General Public License as published by the Free
Packit Service 97d2fb
       Software Foundation; either version 2 of the License, or (at
Packit Service 97d2fb
       your option) any later version
Packit Service 97d2fb
Packit Service 97d2fb
   or both in parallel, as here.
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 GNU
Packit Service 97d2fb
   General Public License for more details.
Packit Service 97d2fb
Packit Service 97d2fb
   You should have received copies of the GNU General Public License and
Packit Service 97d2fb
   the GNU Lesser General Public License along with this program.  If
Packit Service 97d2fb
   not, see <http://www.gnu.org/licenses/>.  */
Packit Service 97d2fb
Packit Service 97d2fb
#ifndef _LIBDWP_H
Packit Service 97d2fb
#define _LIBDWP_H 1
Packit Service 97d2fb
Packit Service 97d2fb
#include <libintl.h>
Packit Service 97d2fb
#include <stdbool.h>
Packit Service 97d2fb
#include <pthread.h>
Packit Service 97d2fb
Packit Service 97d2fb
#include <libdw.h>
Packit Service 97d2fb
#include <dwarf.h>
Packit Service 97d2fb
#include "atomics.h"
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* gettext helper macros.  */
Packit Service 97d2fb
#define _(Str) dgettext ("elfutils", Str)
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Known location expressions already decoded.  */
Packit Service 97d2fb
struct loc_s
Packit Service 97d2fb
{
Packit Service 97d2fb
  void *addr;
Packit Service 97d2fb
  Dwarf_Op *loc;
Packit Service 97d2fb
  size_t nloc;
Packit Service 97d2fb
};
Packit Service 97d2fb
Packit Service 97d2fb
/* Known DW_OP_implicit_value blocks already decoded.
Packit Service 97d2fb
   This overlaps struct loc_s exactly, but only the
Packit Service 97d2fb
   first member really has to match.  */
Packit Service 97d2fb
struct loc_block_s
Packit Service 97d2fb
{
Packit Service 97d2fb
  void *addr;
Packit Service 97d2fb
  unsigned char *data;
Packit Service 97d2fb
  size_t length;
Packit Service 97d2fb
};
Packit Service 97d2fb
Packit Service 97d2fb
/* Already decoded .debug_line units.  */
Packit Service 97d2fb
struct files_lines_s
Packit Service 97d2fb
{
Packit Service 97d2fb
  Dwarf_Off debug_line_offset;
Packit Service 97d2fb
  Dwarf_Files *files;
Packit Service 97d2fb
  Dwarf_Lines *lines;
Packit Service 97d2fb
};
Packit Service 97d2fb
Packit Service 97d2fb
/* Valid indeces for the section data.  */
Packit Service 97d2fb
enum
Packit Service 97d2fb
  {
Packit Service 97d2fb
    IDX_debug_info = 0,
Packit Service 97d2fb
    IDX_debug_types,
Packit Service 97d2fb
    IDX_debug_abbrev,
Packit Service 97d2fb
    IDX_debug_aranges,
Packit Service 97d2fb
    IDX_debug_addr,
Packit Service 97d2fb
    IDX_debug_line,
Packit Service 97d2fb
    IDX_debug_line_str,
Packit Service 97d2fb
    IDX_debug_frame,
Packit Service 97d2fb
    IDX_debug_loc,
Packit Service 97d2fb
    IDX_debug_loclists,
Packit Service 97d2fb
    IDX_debug_pubnames,
Packit Service 97d2fb
    IDX_debug_str,
Packit Service 97d2fb
    IDX_debug_str_offsets,
Packit Service 97d2fb
    IDX_debug_macinfo,
Packit Service 97d2fb
    IDX_debug_macro,
Packit Service 97d2fb
    IDX_debug_ranges,
Packit Service 97d2fb
    IDX_debug_rnglists,
Packit Service 97d2fb
    IDX_gnu_debugaltlink,
Packit Service 97d2fb
    IDX_last
Packit Service 97d2fb
  };
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Error values.  */
Packit Service 97d2fb
enum
Packit Service 97d2fb
{
Packit Service 97d2fb
  DWARF_E_NOERROR = 0,
Packit Service 97d2fb
  DWARF_E_UNKNOWN_ERROR,
Packit Service 97d2fb
  DWARF_E_INVALID_ACCESS,
Packit Service 97d2fb
  DWARF_E_NO_REGFILE,
Packit Service 97d2fb
  DWARF_E_IO_ERROR,
Packit Service 97d2fb
  DWARF_E_INVALID_ELF,
Packit Service 97d2fb
  DWARF_E_NO_DWARF,
Packit Service 97d2fb
  DWARF_E_COMPRESSED_ERROR,
Packit Service 97d2fb
  DWARF_E_NOELF,
Packit Service 97d2fb
  DWARF_E_GETEHDR_ERROR,
Packit Service 97d2fb
  DWARF_E_NOMEM,
Packit Service 97d2fb
  DWARF_E_UNIMPL,
Packit Service 97d2fb
  DWARF_E_INVALID_CMD,
Packit Service 97d2fb
  DWARF_E_INVALID_VERSION,
Packit Service 97d2fb
  DWARF_E_INVALID_FILE,
Packit Service 97d2fb
  DWARF_E_NO_ENTRY,
Packit Service 97d2fb
  DWARF_E_INVALID_DWARF,
Packit Service 97d2fb
  DWARF_E_NO_STRING,
Packit Service 97d2fb
  DWARF_E_NO_DEBUG_STR,
Packit Service 97d2fb
  DWARF_E_NO_DEBUG_LINE_STR,
Packit Service 97d2fb
  DWARF_E_NO_STR_OFFSETS,
Packit Service 97d2fb
  DWARF_E_NO_ADDR,
Packit Service 97d2fb
  DWARF_E_NO_CONSTANT,
Packit Service 97d2fb
  DWARF_E_NO_REFERENCE,
Packit Service 97d2fb
  DWARF_E_INVALID_REFERENCE,
Packit Service 97d2fb
  DWARF_E_NO_DEBUG_LINE,
Packit Service 97d2fb
  DWARF_E_INVALID_DEBUG_LINE,
Packit Service 97d2fb
  DWARF_E_TOO_BIG,
Packit Service 97d2fb
  DWARF_E_VERSION,
Packit Service 97d2fb
  DWARF_E_INVALID_DIR_IDX,
Packit Service 97d2fb
  DWARF_E_ADDR_OUTOFRANGE,
Packit Service 97d2fb
  DWARF_E_NO_DEBUG_LOC,
Packit Service 97d2fb
  DWARF_E_NO_DEBUG_LOCLISTS,
Packit Service 97d2fb
  DWARF_E_NO_LOC_VALUE,
Packit Service 97d2fb
  DWARF_E_NO_BLOCK,
Packit Service 97d2fb
  DWARF_E_INVALID_LINE_IDX,
Packit Service 97d2fb
  DWARF_E_INVALID_ARANGE_IDX,
Packit Service 97d2fb
  DWARF_E_NO_MATCH,
Packit Service 97d2fb
  DWARF_E_NO_FLAG,
Packit Service 97d2fb
  DWARF_E_INVALID_OFFSET,
Packit Service 97d2fb
  DWARF_E_NO_DEBUG_RANGES,
Packit Service 97d2fb
  DWARF_E_NO_DEBUG_RNGLISTS,
Packit Service 97d2fb
  DWARF_E_INVALID_CFI,
Packit Service 97d2fb
  DWARF_E_NO_ALT_DEBUGLINK,
Packit Service 97d2fb
  DWARF_E_INVALID_OPCODE,
Packit Service 97d2fb
  DWARF_E_NOT_CUDIE,
Packit Service 97d2fb
  DWARF_E_UNKNOWN_LANGUAGE,
Packit Service 97d2fb
  DWARF_E_NO_DEBUG_ADDR,
Packit Service 97d2fb
};
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
#include "dwarf_sig8_hash.h"
Packit Service 97d2fb
Packit Service 97d2fb
/* This is the structure representing the debugging state.  */
Packit Service 97d2fb
struct Dwarf
Packit Service 97d2fb
{
Packit Service 97d2fb
  /* The underlying ELF file.  */
Packit Service 97d2fb
  Elf *elf;
Packit Service 97d2fb
Packit Service 97d2fb
  /* The (absolute) path to the ELF dir, if known.  To help locating
Packit Service 97d2fb
     alt and dwo files.  */
Packit Service 97d2fb
  char *debugdir;
Packit Service 97d2fb
Packit Service 97d2fb
  /* dwz alternate DWARF file.  */
Packit Service 97d2fb
  Dwarf *alt_dwarf;
Packit Service 97d2fb
Packit Service 97d2fb
  /* The section data.  */
Packit Service 97d2fb
  Elf_Data *sectiondata[IDX_last];
Packit Service 97d2fb
Packit Service 97d2fb
  /* True if the file has a byte order different from the host.  */
Packit Service 97d2fb
  bool other_byte_order;
Packit Service 97d2fb
Packit Service 97d2fb
  /* If true, we allocated the ELF descriptor ourselves.  */
Packit Service 97d2fb
  bool free_elf;
Packit Service 97d2fb
Packit Service 97d2fb
  /* If >= 0, we allocated the alt_dwarf ourselves and must end it and
Packit Service 97d2fb
     close this file descriptor.  */
Packit Service 97d2fb
  int alt_fd;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Information for traversing the .debug_pubnames section.  This is
Packit Service 97d2fb
     an array and separately allocated with malloc.  */
Packit Service 97d2fb
  struct pubnames_s
Packit Service 97d2fb
  {
Packit Service 97d2fb
    Dwarf_Off cu_offset;
Packit Service 97d2fb
    Dwarf_Off set_start;
Packit Service 97d2fb
    unsigned int cu_header_size;
Packit Service 97d2fb
    int address_len;
Packit Service 97d2fb
  } *pubnames_sets;
Packit Service 97d2fb
  size_t pubnames_nsets;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Search tree for the CUs.  */
Packit Service 97d2fb
  void *cu_tree;
Packit Service 97d2fb
  Dwarf_Off next_cu_offset;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Search tree and sig8 hash table for .debug_types type units.  */
Packit Service 97d2fb
  void *tu_tree;
Packit Service 97d2fb
  Dwarf_Off next_tu_offset;
Packit Service 97d2fb
  Dwarf_Sig8_Hash sig8_hash;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Search tree for split Dwarf associated with CUs in this debug.  */
Packit Service 97d2fb
  void *split_tree;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Search tree for .debug_macro operator tables.  */
Packit Service 97d2fb
  void *macro_ops;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Search tree for decoded .debug_line units.  */
Packit Service 97d2fb
  void *files_lines;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Address ranges.  */
Packit Service 97d2fb
  Dwarf_Aranges *aranges;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Cached info from the CFI section.  */
Packit Service 97d2fb
  struct Dwarf_CFI_s *cfi;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Fake loc CU.  Used when synthesizing attributes for Dwarf_Ops that
Packit Service 97d2fb
     came from a location list entry in dwarf_getlocation_attr.
Packit Service 97d2fb
     Depending on version this is the .debug_loc or .debug_loclists
Packit Service 97d2fb
     section (could be both if mixing CUs with different DWARF versions).  */
Packit Service 97d2fb
  struct Dwarf_CU *fake_loc_cu;
Packit Service 97d2fb
  struct Dwarf_CU *fake_loclists_cu;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Similar for addrx/constx, which will come from .debug_addr section.  */
Packit Service 97d2fb
  struct Dwarf_CU *fake_addr_cu;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Supporting lock for internal memory handling.  Ensures threads that have
Packit Service 97d2fb
     an entry in the mem_tails array are not disturbed by new threads doing
Packit Service 97d2fb
     allocations for this Dwarf.  */
Packit Service 97d2fb
  pthread_rwlock_t mem_rwl;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Internal memory handling.  This is basically a simplified thread-local
Packit Service 97d2fb
     reimplementation of obstacks.  Unfortunately the standard obstack
Packit Service 97d2fb
     implementation is not usable in libraries.  */
Packit Service 97d2fb
  size_t mem_stacks;
Packit Service 97d2fb
  struct libdw_memblock
Packit Service 97d2fb
  {
Packit Service 97d2fb
    size_t size;
Packit Service 97d2fb
    size_t remaining;
Packit Service 97d2fb
    struct libdw_memblock *prev;
Packit Service 97d2fb
    char mem[0];
Packit Service 97d2fb
  } **mem_tails;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Default size of allocated memory blocks.  */
Packit Service 97d2fb
  size_t mem_default_size;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Registered OOM handler.  */
Packit Service 97d2fb
  Dwarf_OOM oom_handler;
Packit Service 97d2fb
};
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Abbreviation representation.  */
Packit Service 97d2fb
struct Dwarf_Abbrev
Packit Service 97d2fb
{
Packit Service 97d2fb
  Dwarf_Off offset;	  /* Offset to start of abbrev into .debug_abbrev.  */
Packit Service 97d2fb
  unsigned char *attrp;   /* Pointer to start of attribute name/form pairs. */
Packit Service 97d2fb
  bool has_children : 1;  /* Whether or not the DIE has children. */
Packit Service 97d2fb
  unsigned int code : 31; /* The (unique) abbrev code.  */
Packit Service 97d2fb
  unsigned int tag;	  /* The tag of the DIE. */
Packit Service 97d2fb
} attribute_packed;
Packit Service 97d2fb
Packit Service 97d2fb
#include "dwarf_abbrev_hash.h"
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Files in line information records.  */
Packit Service 97d2fb
struct Dwarf_Files_s
Packit Service 97d2fb
  {
Packit Service 97d2fb
    unsigned int ndirs;
Packit Service 97d2fb
    unsigned int nfiles;
Packit Service 97d2fb
    struct Dwarf_Fileinfo_s
Packit Service 97d2fb
    {
Packit Service 97d2fb
      char *name;
Packit Service 97d2fb
      Dwarf_Word mtime;
Packit Service 97d2fb
      Dwarf_Word length;
Packit Service 97d2fb
    } info[0];
Packit Service 97d2fb
    /* nfiles of those, followed by char *[ndirs].  */
Packit Service 97d2fb
  };
Packit Service 97d2fb
typedef struct Dwarf_Fileinfo_s Dwarf_Fileinfo;
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Representation of a row in the line table.  */
Packit Service 97d2fb
Packit Service 97d2fb
struct Dwarf_Line_s
Packit Service 97d2fb
{
Packit Service 97d2fb
  Dwarf_Files *files;
Packit Service 97d2fb
Packit Service 97d2fb
  Dwarf_Addr addr;
Packit Service 97d2fb
  unsigned int file;
Packit Service 97d2fb
  int line;
Packit Service 97d2fb
  unsigned short int column;
Packit Service 97d2fb
  unsigned int is_stmt:1;
Packit Service 97d2fb
  unsigned int basic_block:1;
Packit Service 97d2fb
  unsigned int end_sequence:1;
Packit Service 97d2fb
  unsigned int prologue_end:1;
Packit Service 97d2fb
  unsigned int epilogue_begin:1;
Packit Service 97d2fb
  /* The remaining bit fields are not flags, but hold values presumed to be
Packit Service 97d2fb
     small.  All the flags and other bit fields should add up to 48 bits
Packit Service 97d2fb
     to give the whole struct a nice round size.  */
Packit Service 97d2fb
  unsigned int op_index:8;
Packit Service 97d2fb
  unsigned int isa:8;
Packit Service 97d2fb
  unsigned int discriminator:24;
Packit Service 97d2fb
};
Packit Service 97d2fb
Packit Service 97d2fb
struct Dwarf_Lines_s
Packit Service 97d2fb
{
Packit Service 97d2fb
  size_t nlines;
Packit Service 97d2fb
  struct Dwarf_Line_s info[0];
Packit Service 97d2fb
};
Packit Service 97d2fb
Packit Service 97d2fb
/* Representation of address ranges.  */
Packit Service 97d2fb
struct Dwarf_Aranges_s
Packit Service 97d2fb
{
Packit Service 97d2fb
  Dwarf *dbg;
Packit Service 97d2fb
  size_t naranges;
Packit Service 97d2fb
Packit Service 97d2fb
  struct Dwarf_Arange_s
Packit Service 97d2fb
  {
Packit Service 97d2fb
    Dwarf_Addr addr;
Packit Service 97d2fb
    Dwarf_Word length;
Packit Service 97d2fb
    Dwarf_Off offset;
Packit Service 97d2fb
  } info[0];
Packit Service 97d2fb
};
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* CU representation.  */
Packit Service 97d2fb
struct Dwarf_CU
Packit Service 97d2fb
{
Packit Service 97d2fb
  Dwarf *dbg;
Packit Service 97d2fb
  Dwarf_Off start;
Packit Service 97d2fb
  Dwarf_Off end;
Packit Service 97d2fb
  uint8_t address_size;
Packit Service 97d2fb
  uint8_t offset_size;
Packit Service 97d2fb
  uint16_t version;
Packit Service 97d2fb
Packit Service 97d2fb
  size_t sec_idx; /* Normally .debug_info, could be .debug_type or "fake". */
Packit Service 97d2fb
Packit Service 97d2fb
  /* The unit type if version >= 5.  Otherwise 0 for normal CUs (from
Packit Service 97d2fb
     .debug_info) or 1 for v4 type units (from .debug_types).  */
Packit Service 97d2fb
  uint8_t unit_type;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Zero if the unit type doesn't support a die/type offset and/or id/sig.
Packit Service 97d2fb
     Nonzero if it is a v4 type unit or for DWARFv5 units depending on
Packit Service 97d2fb
     unit_type.  */
Packit Service 97d2fb
  size_t subdie_offset;
Packit Service 97d2fb
  uint64_t unit_id8;
Packit Service 97d2fb
Packit Service 97d2fb
  /* If this is a skeleton unit this points to the split compile unit.
Packit Service 97d2fb
     Or the other way around if this is a split compile unit.  Set to -1
Packit Service 97d2fb
     if not yet searched.  Always use __libdw_find_split_unit to access
Packit Service 97d2fb
     this field.  */
Packit Service 97d2fb
  struct Dwarf_CU *split;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Hash table for the abbreviations.  */
Packit Service 97d2fb
  Dwarf_Abbrev_Hash abbrev_hash;
Packit Service 97d2fb
  /* Offset of the first abbreviation.  */
Packit Service 97d2fb
  size_t orig_abbrev_offset;
Packit Service 97d2fb
  /* Offset past last read abbreviation.  */
Packit Service 97d2fb
  size_t last_abbrev_offset;
Packit Service 97d2fb
Packit Service 97d2fb
  /* The srcline information.  */
Packit Service 97d2fb
  Dwarf_Lines *lines;
Packit Service 97d2fb
Packit Service 97d2fb
  /* The source file information.  */
Packit Service 97d2fb
  Dwarf_Files *files;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Known location lists.  */
Packit Service 97d2fb
  void *locs;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Base address for use with ranges and locs.
Packit Service 97d2fb
     Don't access directly, call __libdw_cu_base_address.  */
Packit Service 97d2fb
  Dwarf_Addr base_address;
Packit Service 97d2fb
Packit Service 97d2fb
  /* The offset into the .debug_addr section where index zero begins.
Packit Service 97d2fb
     Don't access directly, call __libdw_cu_addr_base.  */
Packit Service 97d2fb
  Dwarf_Off addr_base;
Packit Service 97d2fb
Packit Service 97d2fb
  /* The offset into the .debug_str_offsets section where index zero begins.
Packit Service 97d2fb
     Don't access directly, call __libdw_cu_str_off_base.  */
Packit Service 97d2fb
  Dwarf_Off str_off_base;
Packit Service 97d2fb
Packit Service 97d2fb
  /* The offset into the .debug_ranges section to use for GNU
Packit Service 97d2fb
     DebugFission split units.  Don't access directly, call
Packit Service 97d2fb
     __libdw_cu_ranges_base.  */
Packit Service 97d2fb
  Dwarf_Off ranges_base;
Packit Service 97d2fb
Packit Service 97d2fb
  /* The start of the offset table in .debug_loclists.
Packit Service 97d2fb
     Don't access directly, call __libdw_cu_locs_base.  */
Packit Service 97d2fb
  Dwarf_Off locs_base;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Memory boundaries of this CU.  */
Packit Service 97d2fb
  void *startp;
Packit Service 97d2fb
  void *endp;
Packit Service 97d2fb
};
Packit Service 97d2fb
Packit Service 97d2fb
#define ISV4TU(cu) ((cu)->version == 4 && (cu)->sec_idx == IDX_debug_types)
Packit Service 97d2fb
Packit Service 97d2fb
/* Compute the offset of a CU's first DIE from the CU offset.
Packit Service 97d2fb
   CU must be a valid/known version/unit_type.  */
Packit Service 97d2fb
static inline Dwarf_Off
Packit Service 97d2fb
__libdw_first_die_from_cu_start (Dwarf_Off cu_start,
Packit Service 97d2fb
				 uint8_t offset_size,
Packit Service 97d2fb
				 uint16_t version,
Packit Service 97d2fb
				 uint8_t unit_type)
Packit Service 97d2fb
{
Packit Service 97d2fb
/*
Packit Service 97d2fb
  assert (offset_size == 4 || offset_size == 8);
Packit Service 97d2fb
  assert (version >= 2 && version <= 5);
Packit Service 97d2fb
  assert (unit_type == DW_UT_compile
Packit Service 97d2fb
	  || unit_type == DW_UT_partial
Packit Service 97d2fb
	  || unit_type == DW_UT_skeleton
Packit Service 97d2fb
	  || unit_type == DW_UT_split_compile
Packit Service 97d2fb
	  || unit_type == DW_UT_type
Packit Service 97d2fb
	  || unit_type == DW_UT_split_type);
Packit Service 97d2fb
*/
Packit Service 97d2fb
Packit Service 97d2fb
  Dwarf_Off off = cu_start;
Packit Service 97d2fb
  if (version < 5)
Packit Service 97d2fb
    {
Packit Service 97d2fb
   /*
Packit Service 97d2fb
        LEN       VER     OFFSET    ADDR
Packit Service 97d2fb
      4-bytes + 2-bytes + 4-bytes + 1-byte  for 32-bit dwarf
Packit Service 97d2fb
     12-bytes + 2-bytes + 8-bytes + 1-byte  for 64-bit dwarf
Packit Service 97d2fb
   or in .debug_types, 			     SIGNATURE TYPE-OFFSET
Packit Service 97d2fb
      4-bytes + 2-bytes + 4-bytes + 1-byte + 8-bytes + 4-bytes  for 32-bit
Packit Service 97d2fb
     12-bytes + 2-bytes + 8-bytes + 1-byte + 8-bytes + 8-bytes  for 64-bit
Packit Service 97d2fb
Packit Service 97d2fb
   Note the trick in the computation.  If the offset_size is 4
Packit Service 97d2fb
   the '- 4' term changes the '3 *' (or '4 *') into a '2 *' (or '3 *).
Packit Service 97d2fb
   If the offset_size is 8 it accounts for the 4-byte escape value
Packit Service 97d2fb
   used at the start of the length.  */
Packit Service 97d2fb
      if (unit_type != DW_UT_type)
Packit Service 97d2fb
	off += 3 * offset_size - 4 + 3;
Packit Service 97d2fb
      else
Packit Service 97d2fb
	off += 4 * offset_size - 4 + 3 + 8;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  else
Packit Service 97d2fb
    {
Packit Service 97d2fb
     /*
Packit Service 97d2fb
        LEN       VER      TYPE     ADDR     OFFSET   SIGNATURE  TYPE-OFFSET
Packit Service 97d2fb
      4-bytes + 2-bytes + 1-byte + 1-byte + 4-bytes + 8-bytes + 4-bytes 32-bit
Packit Service 97d2fb
     12-bytes + 2-bytes + 1-byte + 1-byte + 8-bytes + 8-bytes + 8-bytes 64-bit
Packit Service 97d2fb
        Both signature and type offset are optional.
Packit Service 97d2fb
Packit Service 97d2fb
        Note same 4/8 offset size trick as above.
Packit Service 97d2fb
        We explicitly ignore unknow unit types (see asserts above).  */
Packit Service 97d2fb
      off += 3 * offset_size - 4 + 4;
Packit Service 97d2fb
      if (unit_type == DW_UT_skeleton || unit_type == DW_UT_split_compile
Packit Service 97d2fb
	  || unit_type == DW_UT_type || unit_type == DW_UT_split_type)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  off += 8;
Packit Service 97d2fb
	  if (unit_type == DW_UT_type || unit_type == DW_UT_split_type)
Packit Service 97d2fb
	    off += offset_size;
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  return off;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static inline Dwarf_Off
Packit Service 97d2fb
__libdw_first_die_off_from_cu (struct Dwarf_CU *cu)
Packit Service 97d2fb
{
Packit Service 97d2fb
  return __libdw_first_die_from_cu_start (cu->start,
Packit Service 97d2fb
					  cu->offset_size,
Packit Service 97d2fb
					  cu->version,
Packit Service 97d2fb
					  cu->unit_type);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
#define CUDIE(fromcu)							      \
Packit Service 97d2fb
  ((Dwarf_Die)								      \
Packit Service 97d2fb
   {									      \
Packit Service 97d2fb
     .cu = (fromcu),							      \
Packit Service 97d2fb
     .addr = ((char *) (fromcu)->dbg->sectiondata[cu_sec_idx (fromcu)]->d_buf \
Packit Service 97d2fb
	      + __libdw_first_die_off_from_cu (fromcu))			      \
Packit Service 97d2fb
   })
Packit Service 97d2fb
Packit Service 97d2fb
#define SUBDIE(fromcu)							      \
Packit Service 97d2fb
  ((Dwarf_Die)								      \
Packit Service 97d2fb
   {									      \
Packit Service 97d2fb
     .cu = (fromcu),							      \
Packit Service 97d2fb
     .addr = ((char *) (fromcu)->dbg->sectiondata[cu_sec_idx (fromcu)]->d_buf \
Packit Service 97d2fb
	      + (fromcu)->start + (fromcu)->subdie_offset)		      \
Packit Service 97d2fb
   })
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Prototype of a single .debug_macro operator.  */
Packit Service 97d2fb
typedef struct
Packit Service 97d2fb
{
Packit Service 97d2fb
  Dwarf_Word nforms;
Packit Service 97d2fb
  unsigned char const *forms;
Packit Service 97d2fb
} Dwarf_Macro_Op_Proto;
Packit Service 97d2fb
Packit Service 97d2fb
/* Prototype table.  */
Packit Service 97d2fb
typedef struct
Packit Service 97d2fb
{
Packit Service 97d2fb
  /* Offset of .debug_macro section.  */
Packit Service 97d2fb
  Dwarf_Off offset;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Offset of associated .debug_line section.  */
Packit Service 97d2fb
  Dwarf_Off line_offset;
Packit Service 97d2fb
Packit Service 97d2fb
  /* The source file information.  */
Packit Service 97d2fb
  Dwarf_Files *files;
Packit Service 97d2fb
Packit Service 97d2fb
  /* If this macro unit was opened through dwarf_getmacros or
Packit Service 97d2fb
     dwarf_getmacros_die, this caches value of DW_AT_comp_dir, if
Packit Service 97d2fb
     present.  */
Packit Service 97d2fb
  const char *comp_dir;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Header length.  */
Packit Service 97d2fb
  Dwarf_Half header_len;
Packit Service 97d2fb
Packit Service 97d2fb
  uint16_t version;
Packit Service 97d2fb
  bool is_64bit;
Packit Service 97d2fb
  uint8_t sec_index;	/* IDX_debug_macro or IDX_debug_macinfo.  */
Packit Service 97d2fb
Packit Service 97d2fb
  /* Shows where in TABLE each opcode is defined.  Since opcode 0 is
Packit Service 97d2fb
     never used, it stores index of opcode X in X-1'th element.  The
Packit Service 97d2fb
     value of 0xff means not stored at all.  */
Packit Service 97d2fb
  unsigned char opcodes[255];
Packit Service 97d2fb
Packit Service 97d2fb
  /* Individual opcode prototypes.  */
Packit Service 97d2fb
  Dwarf_Macro_Op_Proto table[];
Packit Service 97d2fb
} Dwarf_Macro_Op_Table;
Packit Service 97d2fb
Packit Service 97d2fb
struct Dwarf_Macro_s
Packit Service 97d2fb
{
Packit Service 97d2fb
  Dwarf_Macro_Op_Table *table;
Packit Service 97d2fb
  Dwarf_Attribute *attributes;
Packit Service 97d2fb
  uint8_t opcode;
Packit Service 97d2fb
};
Packit Service 97d2fb
Packit Service 97d2fb
static inline Dwarf_Word
Packit Service 97d2fb
libdw_macro_nforms (Dwarf_Macro *macro)
Packit Service 97d2fb
{
Packit Service 97d2fb
  return macro->table->table[macro->table->opcodes[macro->opcode - 1]].nforms;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
/* Returns true for any allowed FORM in the opcode_operands_table as
Packit Service 97d2fb
   mentioned in the DWARF5 spec (6.3.1 Macro Information Header).
Packit Service 97d2fb
   Or those mentioned in DWARF5 spec (6.2.4.2 Vendor-defined Content
Packit Service 97d2fb
   Descriptions) for the directory/file table (plus DW_FORM_strp_sup).  */
Packit Service 97d2fb
static inline bool
Packit Service 97d2fb
libdw_valid_user_form (int form)
Packit Service 97d2fb
{
Packit Service 97d2fb
  switch (form)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      case DW_FORM_block:
Packit Service 97d2fb
      case DW_FORM_block1:
Packit Service 97d2fb
      case DW_FORM_block2:
Packit Service 97d2fb
      case DW_FORM_block4:
Packit Service 97d2fb
      case DW_FORM_data1:
Packit Service 97d2fb
      case DW_FORM_data2:
Packit Service 97d2fb
      case DW_FORM_data4:
Packit Service 97d2fb
      case DW_FORM_data8:
Packit Service 97d2fb
      case DW_FORM_data16:
Packit Service 97d2fb
      case DW_FORM_flag:
Packit Service 97d2fb
      case DW_FORM_line_strp:
Packit Service 97d2fb
      case DW_FORM_sdata:
Packit Service 97d2fb
      case DW_FORM_sec_offset:
Packit Service 97d2fb
      case DW_FORM_string:
Packit Service 97d2fb
      case DW_FORM_strp:
Packit Service 97d2fb
      case DW_FORM_strp_sup:
Packit Service 97d2fb
      case DW_FORM_strx:
Packit Service 97d2fb
      case DW_FORM_strx1:
Packit Service 97d2fb
      case DW_FORM_strx2:
Packit Service 97d2fb
      case DW_FORM_strx3:
Packit Service 97d2fb
      case DW_FORM_strx4:
Packit Service 97d2fb
      case DW_FORM_udata:
Packit Service 97d2fb
	return true;
Packit Service 97d2fb
      default:
Packit Service 97d2fb
	return false;
Packit Service 97d2fb
    }
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* We have to include the file at this point because the inline
Packit Service 97d2fb
   functions access internals of the Dwarf structure.  */
Packit Service 97d2fb
#include "memory-access.h"
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Set error value.  */
Packit Service 97d2fb
extern void __libdw_seterrno (int value) internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Memory handling, the easy parts.  */
Packit Service 97d2fb
#define libdw_alloc(dbg, type, tsize, cnt) \
Packit Service 97d2fb
  ({ struct libdw_memblock *_tail = __libdw_alloc_tail(dbg);		      \
Packit Service 97d2fb
     size_t _required = (tsize) * (cnt);				      \
Packit Service 97d2fb
     type *_result = (type *) (_tail->mem + (_tail->size - _tail->remaining));\
Packit Service 97d2fb
     size_t _padding = ((__alignof (type)				      \
Packit Service 97d2fb
			 - ((uintptr_t) _result & (__alignof (type) - 1)))    \
Packit Service 97d2fb
			& (__alignof (type) - 1));			      \
Packit Service 97d2fb
     if (unlikely (_tail->remaining < _required + _padding))		      \
Packit Service 97d2fb
       _result = (type *) __libdw_allocate (dbg, _required, __alignof (type));\
Packit Service 97d2fb
     else								      \
Packit Service 97d2fb
       {								      \
Packit Service 97d2fb
	 _required += _padding;						      \
Packit Service 97d2fb
	 _result = (type *) ((char *) _result + _padding);		      \
Packit Service 97d2fb
	 _tail->remaining -= _required;					      \
Packit Service 97d2fb
       }								      \
Packit Service 97d2fb
     _result; })
Packit Service 97d2fb
Packit Service 97d2fb
#define libdw_typed_alloc(dbg, type) \
Packit Service 97d2fb
  libdw_alloc (dbg, type, sizeof (type), 1)
Packit Service 97d2fb
Packit Service 97d2fb
/* Can only be used to undo the last libdw_alloc.  */
Packit Service 97d2fb
#define libdw_unalloc(dbg, type, tsize, cnt) \
Packit Service 97d2fb
  ({ struct libdw_memblock *_tail = __libdw_thread_tail (dbg);		      \
Packit Service 97d2fb
     size_t _required = (tsize) * (cnt);				      \
Packit Service 97d2fb
     /* We cannot know the padding, it is lost.  */			      \
Packit Service 97d2fb
     _tail->remaining += _required; })					      \
Packit Service 97d2fb
Packit Service 97d2fb
#define libdw_typed_unalloc(dbg, type) \
Packit Service 97d2fb
  libdw_unalloc (dbg, type, sizeof (type), 1)
Packit Service 97d2fb
Packit Service 97d2fb
/* Callback to choose a thread-local memory allocation stack.  */
Packit Service 97d2fb
extern struct libdw_memblock *__libdw_alloc_tail (Dwarf* dbg)
Packit Service 97d2fb
     __nonnull_attribute__ (1);
Packit Service 97d2fb
Packit Service 97d2fb
extern struct libdw_memblock *__libdw_thread_tail (Dwarf* dbg)
Packit Service 97d2fb
     __nonnull_attribute__ (1);
Packit Service 97d2fb
Packit Service 97d2fb
/* Callback to allocate more.  */
Packit Service 97d2fb
extern void *__libdw_allocate (Dwarf *dbg, size_t minsize, size_t align)
Packit Service 97d2fb
     __attribute__ ((__malloc__)) __nonnull_attribute__ (1);
Packit Service 97d2fb
Packit Service 97d2fb
/* Default OOM handler.  */
Packit Service 97d2fb
extern void __libdw_oom (void) __attribute ((noreturn)) attribute_hidden;
Packit Service 97d2fb
Packit Service 97d2fb
/* Read next unit (or v4 debug type) and return next offset.  Doesn't
Packit Service 97d2fb
   create an actual Dwarf_CU just provides necessary header fields.  */
Packit Service 97d2fb
extern int
Packit Service 97d2fb
internal_function
Packit Service 97d2fb
__libdw_next_unit (Dwarf *dbg, bool v4_debug_types, Dwarf_Off off,
Packit Service 97d2fb
		   Dwarf_Off *next_off, size_t *header_sizep,
Packit Service 97d2fb
		   Dwarf_Half *versionp, uint8_t *unit_typep,
Packit Service 97d2fb
		   Dwarf_Off *abbrev_offsetp, uint8_t *address_sizep,
Packit Service 97d2fb
		   uint8_t *offset_sizep, uint64_t *unit_id8p,
Packit Service 97d2fb
		   Dwarf_Off *subdie_offsetp)
Packit Service 97d2fb
     __nonnull_attribute__ (4) internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
/* Allocate the internal data for a unit not seen before.  */
Packit Service 97d2fb
extern struct Dwarf_CU *__libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
Packit Service 97d2fb
     __nonnull_attribute__ (1) internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
/* Find CU for given offset.  */
Packit Service 97d2fb
extern struct Dwarf_CU *__libdw_findcu (Dwarf *dbg, Dwarf_Off offset, bool tu)
Packit Service 97d2fb
     __nonnull_attribute__ (1) internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
/* Find CU for given DIE address.  */
Packit Service 97d2fb
extern struct Dwarf_CU *__libdw_findcu_addr (Dwarf *dbg, void *addr)
Packit Service 97d2fb
     __nonnull_attribute__ (1) internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
/* Find split Dwarf for given DIE address.  */
Packit Service 97d2fb
extern struct Dwarf *__libdw_find_split_dbg_addr (Dwarf *dbg, void *addr)
Packit Service 97d2fb
     __nonnull_attribute__ (1) internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
/* Find the split (or skeleton) unit.  */
Packit Service 97d2fb
extern struct Dwarf_CU *__libdw_find_split_unit (Dwarf_CU *cu)
Packit Service 97d2fb
     internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
/* Get abbreviation with given code.  */
Packit Service 97d2fb
extern Dwarf_Abbrev *__libdw_findabbrev (struct Dwarf_CU *cu,
Packit Service 97d2fb
					 unsigned int code)
Packit Service 97d2fb
     __nonnull_attribute__ (1) internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
/* Get abbreviation at given offset.  */
Packit Service 97d2fb
extern Dwarf_Abbrev *__libdw_getabbrev (Dwarf *dbg, struct Dwarf_CU *cu,
Packit Service 97d2fb
					Dwarf_Off offset, size_t *lengthp,
Packit Service 97d2fb
					Dwarf_Abbrev *result)
Packit Service 97d2fb
     __nonnull_attribute__ (1) internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
/* Get abbreviation of given DIE, and optionally set *READP to the DIE memory
Packit Service 97d2fb
   just past the abbreviation code.  */
Packit Service 97d2fb
static inline Dwarf_Abbrev *
Packit Service 97d2fb
__nonnull_attribute__ (1)
Packit Service 97d2fb
__libdw_dieabbrev (Dwarf_Die *die, const unsigned char **readp)
Packit Service 97d2fb
{
Packit Service 97d2fb
  /* Do we need to get the abbreviation, or need to read after the code?  */
Packit Service 97d2fb
  if (die->abbrev == NULL || readp != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* Get the abbreviation code.  */
Packit Service 97d2fb
      unsigned int code;
Packit Service 97d2fb
      const unsigned char *addr = die->addr;
Packit Service 97d2fb
      if (unlikely (die->cu == NULL
Packit Service 97d2fb
		    || addr >= (const unsigned char *) die->cu->endp))
Packit Service 97d2fb
	return die->abbrev = DWARF_END_ABBREV;
Packit Service 97d2fb
      get_uleb128 (code, addr, die->cu->endp);
Packit Service 97d2fb
      if (readp != NULL)
Packit Service 97d2fb
	*readp = addr;
Packit Service 97d2fb
Packit Service 97d2fb
      /* Find the abbreviation.  */
Packit Service 97d2fb
      if (die->abbrev == NULL)
Packit Service 97d2fb
	die->abbrev = __libdw_findabbrev (die->cu, code);
Packit Service 97d2fb
    }
Packit Service 97d2fb
  return die->abbrev;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
/* Helper functions for form handling.  */
Packit Service 97d2fb
extern size_t __libdw_form_val_compute_len (struct Dwarf_CU *cu,
Packit Service 97d2fb
					    unsigned int form,
Packit Service 97d2fb
					    const unsigned char *valp)
Packit Service 97d2fb
     __nonnull_attribute__ (1, 3) internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
/* Find the length of a form attribute in DIE/info data.  */
Packit Service 97d2fb
static inline size_t
Packit Service 97d2fb
__nonnull_attribute__ (1, 3)
Packit Service 97d2fb
__libdw_form_val_len (struct Dwarf_CU *cu, unsigned int form,
Packit Service 97d2fb
		      const unsigned char *valp)
Packit Service 97d2fb
{
Packit Service 97d2fb
  /* Small lookup table of forms with fixed lengths.  Absent indexes are
Packit Service 97d2fb
     initialized 0, so any truly desired 0 is set to 0x80 and masked.  */
Packit Service 97d2fb
  static const uint8_t form_lengths[] =
Packit Service 97d2fb
    {
Packit Service 97d2fb
      [DW_FORM_flag_present] = 0x80,
Packit Service 97d2fb
      [DW_FORM_implicit_const] = 0x80, /* Value is in abbrev, not in info.  */
Packit Service 97d2fb
Packit Service 97d2fb
      [DW_FORM_flag] = 1,
Packit Service 97d2fb
      [DW_FORM_data1] = 1, [DW_FORM_ref1] = 1,
Packit Service 97d2fb
      [DW_FORM_addrx1] = 1, [DW_FORM_strx1] = 1,
Packit Service 97d2fb
Packit Service 97d2fb
      [DW_FORM_data2] = 2, [DW_FORM_ref2] = 2,
Packit Service 97d2fb
      [DW_FORM_addrx2] = 2, [DW_FORM_strx2] = 2,
Packit Service 97d2fb
Packit Service 97d2fb
      [DW_FORM_addrx3] = 3, [DW_FORM_strx3] = 3,
Packit Service 97d2fb
Packit Service 97d2fb
      [DW_FORM_data4] = 4, [DW_FORM_ref4] = 4, [DW_FORM_ref_sup4] = 4,
Packit Service 97d2fb
      [DW_FORM_addrx4] = 4, [DW_FORM_strx4] = 4,
Packit Service 97d2fb
Packit Service 97d2fb
      [DW_FORM_ref_sig8] = 8,
Packit Service 97d2fb
      [DW_FORM_data8] = 8, [DW_FORM_ref8] = 8, [DW_FORM_ref_sup8] = 8,
Packit Service 97d2fb
Packit Service 97d2fb
      [DW_FORM_data16] = 16,
Packit Service 97d2fb
    };
Packit Service 97d2fb
Packit Service 97d2fb
  /* Return immediately for forms with fixed lengths.  */
Packit Service 97d2fb
  if (form < sizeof form_lengths / sizeof form_lengths[0])
Packit Service 97d2fb
    {
Packit Service 97d2fb
      uint8_t len = form_lengths[form];
Packit Service 97d2fb
      if (len != 0)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  const unsigned char *endp = cu->endp;
Packit Service 97d2fb
	  len &= 0x7f; /* Mask to allow 0x80 -> 0.  */
Packit Service 97d2fb
	  if (unlikely (len > (size_t) (endp - valp)))
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
Packit Service 97d2fb
	      return -1;
Packit Service 97d2fb
	    }
Packit Service 97d2fb
	  return len;
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* Other forms require some computation.  */
Packit Service 97d2fb
  return __libdw_form_val_compute_len (cu, form, valp);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
/* Helper function for DW_FORM_ref* handling.  */
Packit Service 97d2fb
extern int __libdw_formref (Dwarf_Attribute *attr, Dwarf_Off *return_offset)
Packit Service 97d2fb
     __nonnull_attribute__ (1, 2) internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Helper function to locate attribute.  */
Packit Service 97d2fb
extern unsigned char *__libdw_find_attr (Dwarf_Die *die,
Packit Service 97d2fb
					 unsigned int search_name,
Packit Service 97d2fb
					 unsigned int *codep,
Packit Service 97d2fb
					 unsigned int *formp)
Packit Service 97d2fb
     __nonnull_attribute__ (1) internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
/* Helper function to access integer attribute.  */
Packit Service 97d2fb
extern int __libdw_attr_intval (Dwarf_Die *die, int *valp, int attval)
Packit Service 97d2fb
     __nonnull_attribute__ (1, 2) internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
/* Helper function to walk scopes.  */
Packit Service 97d2fb
struct Dwarf_Die_Chain
Packit Service 97d2fb
{
Packit Service 97d2fb
  Dwarf_Die die;
Packit Service 97d2fb
  struct Dwarf_Die_Chain *parent;
Packit Service 97d2fb
  bool prune;			/* The PREVISIT function can set this.  */
Packit Service 97d2fb
};
Packit Service 97d2fb
extern int __libdw_visit_scopes (unsigned int depth,
Packit Service 97d2fb
				 struct Dwarf_Die_Chain *root,
Packit Service 97d2fb
				 struct Dwarf_Die_Chain *imports,
Packit Service 97d2fb
				 int (*previsit) (unsigned int depth,
Packit Service 97d2fb
						  struct Dwarf_Die_Chain *,
Packit Service 97d2fb
						  void *arg),
Packit Service 97d2fb
				 int (*postvisit) (unsigned int depth,
Packit Service 97d2fb
						   struct Dwarf_Die_Chain *,
Packit Service 97d2fb
						   void *arg),
Packit Service 97d2fb
				 void *arg)
Packit Service 97d2fb
  __nonnull_attribute__ (2, 4) internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
/* Parse a DWARF Dwarf_Block into an array of Dwarf_Op's,
Packit Service 97d2fb
   and cache the result (via tsearch).  */
Packit Service 97d2fb
extern int __libdw_intern_expression (Dwarf *dbg,
Packit Service 97d2fb
				      bool other_byte_order,
Packit Service 97d2fb
				      unsigned int address_size,
Packit Service 97d2fb
				      unsigned int ref_size,
Packit Service 97d2fb
				      void **cache, const Dwarf_Block *block,
Packit Service 97d2fb
				      bool cfap, bool valuep,
Packit Service 97d2fb
				      Dwarf_Op **llbuf, size_t *listlen,
Packit Service 97d2fb
				      int sec_index)
Packit Service 97d2fb
  __nonnull_attribute__ (5, 6, 9, 10) internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
extern Dwarf_Die *__libdw_offdie (Dwarf *dbg, Dwarf_Off offset,
Packit Service 97d2fb
				  Dwarf_Die *result, bool debug_types)
Packit Service 97d2fb
  internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Return error code of last failing function call.  This value is kept
Packit Service 97d2fb
   separately for each thread.  */
Packit Service 97d2fb
extern int __dwarf_errno_internal (void);
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Reader hooks.  */
Packit Service 97d2fb
Packit Service 97d2fb
/* Relocation hooks return -1 on error (in that case the error code
Packit Service 97d2fb
   must already have been set), 0 if there is no relocation and 1 if a
Packit Service 97d2fb
   relocation was present.*/
Packit Service 97d2fb
Packit Service 97d2fb
static inline int
Packit Service 97d2fb
__libdw_relocate_address (Dwarf *dbg __attribute__ ((unused)),
Packit Service 97d2fb
			  int sec_index __attribute__ ((unused)),
Packit Service 97d2fb
			  const void *addr __attribute__ ((unused)),
Packit Service 97d2fb
			  int width __attribute__ ((unused)),
Packit Service 97d2fb
			  Dwarf_Addr *val __attribute__ ((unused)))
Packit Service 97d2fb
{
Packit Service 97d2fb
  return 0;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static inline int
Packit Service 97d2fb
__libdw_relocate_offset (Dwarf *dbg __attribute__ ((unused)),
Packit Service 97d2fb
			 int sec_index __attribute__ ((unused)),
Packit Service 97d2fb
			 const void *addr __attribute__ ((unused)),
Packit Service 97d2fb
			 int width __attribute__ ((unused)),
Packit Service 97d2fb
			 Dwarf_Off *val __attribute__ ((unused)))
Packit Service 97d2fb
{
Packit Service 97d2fb
  return 0;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static inline Elf_Data *
Packit Service 97d2fb
__libdw_checked_get_data (Dwarf *dbg, int sec_index)
Packit Service 97d2fb
{
Packit Service 97d2fb
  Elf_Data *data = dbg->sectiondata[sec_index];
Packit Service 97d2fb
  if (unlikely (data == NULL)
Packit Service 97d2fb
      || unlikely (data->d_buf == NULL))
Packit Service 97d2fb
    {
Packit Service 97d2fb
      __libdw_seterrno (DWARF_E_INVALID_DWARF);
Packit Service 97d2fb
      return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  return data;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static inline int
Packit Service 97d2fb
__libdw_offset_in_section (Dwarf *dbg, int sec_index,
Packit Service 97d2fb
			   Dwarf_Off offset, size_t size)
Packit Service 97d2fb
{
Packit Service 97d2fb
  Elf_Data *data = __libdw_checked_get_data (dbg, sec_index);
Packit Service 97d2fb
  if (data == NULL)
Packit Service 97d2fb
    return -1;
Packit Service 97d2fb
  if (unlikely (offset > data->d_size)
Packit Service 97d2fb
      || unlikely (data->d_size < size)
Packit Service 97d2fb
      || unlikely (offset > data->d_size - size))
Packit Service 97d2fb
    {
Packit Service 97d2fb
      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
Packit Service 97d2fb
      return -1;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  return 0;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static inline bool
Packit Service 97d2fb
__libdw_in_section (Dwarf *dbg, int sec_index,
Packit Service 97d2fb
		    const void *addr, size_t size)
Packit Service 97d2fb
{
Packit Service 97d2fb
  Elf_Data *data = __libdw_checked_get_data (dbg, sec_index);
Packit Service 97d2fb
  if (data == NULL)
Packit Service 97d2fb
    return false;
Packit Service 97d2fb
  if (unlikely (addr < data->d_buf)
Packit Service 97d2fb
      || unlikely (data->d_size < size)
Packit Service 97d2fb
      || unlikely ((size_t)(addr - data->d_buf) > data->d_size - size))
Packit Service 97d2fb
    {
Packit Service 97d2fb
      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
Packit Service 97d2fb
      return false;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  return true;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
#define READ_AND_RELOCATE(RELOC_HOOK, VAL)				\
Packit Service 97d2fb
  ({									\
Packit Service 97d2fb
    if (!__libdw_in_section (dbg, sec_index, addr, width))		\
Packit Service 97d2fb
      return -1;							\
Packit Service 97d2fb
									\
Packit Service 97d2fb
    const unsigned char *orig_addr = addr;				\
Packit Service 97d2fb
    if (width == 4)							\
Packit Service 97d2fb
      VAL = read_4ubyte_unaligned_inc (dbg, addr);			\
Packit Service 97d2fb
    else								\
Packit Service 97d2fb
      VAL = read_8ubyte_unaligned_inc (dbg, addr);			\
Packit Service 97d2fb
									\
Packit Service 97d2fb
    int status = RELOC_HOOK (dbg, sec_index, orig_addr, width, &VAL);	\
Packit Service 97d2fb
    if (status < 0)							\
Packit Service 97d2fb
      return status;							\
Packit Service 97d2fb
    status > 0;								\
Packit Service 97d2fb
   })
Packit Service 97d2fb
Packit Service 97d2fb
static inline int
Packit Service 97d2fb
__libdw_read_address_inc (Dwarf *dbg,
Packit Service 97d2fb
			  int sec_index, const unsigned char **addrp,
Packit Service 97d2fb
			  int width, Dwarf_Addr *ret)
Packit Service 97d2fb
{
Packit Service 97d2fb
  const unsigned char *addr = *addrp;
Packit Service 97d2fb
  READ_AND_RELOCATE (__libdw_relocate_address, (*ret));
Packit Service 97d2fb
  *addrp = addr;
Packit Service 97d2fb
  return 0;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static inline int
Packit Service 97d2fb
__libdw_read_address (Dwarf *dbg,
Packit Service 97d2fb
		      int sec_index, const unsigned char *addr,
Packit Service 97d2fb
		      int width, Dwarf_Addr *ret)
Packit Service 97d2fb
{
Packit Service 97d2fb
  READ_AND_RELOCATE (__libdw_relocate_address, (*ret));
Packit Service 97d2fb
  return 0;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static inline int
Packit Service 97d2fb
__libdw_read_offset_inc (Dwarf *dbg,
Packit Service 97d2fb
			 int sec_index, const unsigned char **addrp,
Packit Service 97d2fb
			 int width, Dwarf_Off *ret, int sec_ret,
Packit Service 97d2fb
			 size_t size)
Packit Service 97d2fb
{
Packit Service 97d2fb
  const unsigned char *addr = *addrp;
Packit Service 97d2fb
  READ_AND_RELOCATE (__libdw_relocate_offset, (*ret));
Packit Service 97d2fb
  *addrp = addr;
Packit Service 97d2fb
  return __libdw_offset_in_section (dbg, sec_ret, *ret, size);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static inline int
Packit Service 97d2fb
__libdw_read_offset (Dwarf *dbg, Dwarf *dbg_ret,
Packit Service 97d2fb
		     int sec_index, const unsigned char *addr,
Packit Service 97d2fb
		     int width, Dwarf_Off *ret, int sec_ret,
Packit Service 97d2fb
		     size_t size)
Packit Service 97d2fb
{
Packit Service 97d2fb
  READ_AND_RELOCATE (__libdw_relocate_offset, (*ret));
Packit Service 97d2fb
  return __libdw_offset_in_section (dbg_ret, sec_ret, *ret, size);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static inline size_t
Packit Service 97d2fb
cu_sec_idx (struct Dwarf_CU *cu)
Packit Service 97d2fb
{
Packit Service 97d2fb
  return cu->sec_idx;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static inline bool
Packit Service 97d2fb
is_cudie (Dwarf_Die *cudie)
Packit Service 97d2fb
{
Packit Service 97d2fb
  return cudie->cu != NULL && CUDIE (cudie->cu).addr == cudie->addr;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
/* Read up begin/end pair and increment read pointer.
Packit Service 97d2fb
    - If it's normal range record, set up *BEGINP and *ENDP and return 0.
Packit Service 97d2fb
    - If it's base address selection record, set up *BASEP and return 1.
Packit Service 97d2fb
    - If it's end of rangelist, don't set anything and return 2
Packit Service 97d2fb
    - If an error occurs, don't set anything and return <0.  */
Packit Service 97d2fb
int __libdw_read_begin_end_pair_inc (Dwarf_CU *cu, int sec_index,
Packit Service 97d2fb
				     const unsigned char **readp,
Packit Service 97d2fb
				     const unsigned char *readend,
Packit Service 97d2fb
				     int width,
Packit Service 97d2fb
				     Dwarf_Addr *beginp, Dwarf_Addr *endp,
Packit Service 97d2fb
				     Dwarf_Addr *basep)
Packit Service 97d2fb
  internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
const unsigned char * __libdw_formptr (Dwarf_Attribute *attr, int sec_index,
Packit Service 97d2fb
				       int err_nodata,
Packit Service 97d2fb
				       const unsigned char **endpp,
Packit Service 97d2fb
				       Dwarf_Off *offsetp)
Packit Service 97d2fb
  internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
/* Fills in the given attribute to point at an empty location expression.  */
Packit Service 97d2fb
void __libdw_empty_loc_attr (Dwarf_Attribute *attr)
Packit Service 97d2fb
  internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
/* Load .debug_line unit at DEBUG_LINE_OFFSET.  COMP_DIR is a value of
Packit Service 97d2fb
   DW_AT_comp_dir or NULL if that attribute is not available.  Caches
Packit Service 97d2fb
   the loaded unit and optionally set *LINESP and/or *FILESP (if not
Packit Service 97d2fb
   NULL) with loaded information.  Returns 0 for success or a negative
Packit Service 97d2fb
   value for failure.  */
Packit Service 97d2fb
int __libdw_getsrclines (Dwarf *dbg, Dwarf_Off debug_line_offset,
Packit Service 97d2fb
			 const char *comp_dir, unsigned address_size,
Packit Service 97d2fb
			 Dwarf_Lines **linesp, Dwarf_Files **filesp)
Packit Service 97d2fb
  internal_function
Packit Service 97d2fb
  __nonnull_attribute__ (1);
Packit Service 97d2fb
Packit Service 97d2fb
/* Load and return value of DW_AT_comp_dir from CUDIE.  */
Packit Service 97d2fb
const char *__libdw_getcompdir (Dwarf_Die *cudie);
Packit Service 97d2fb
Packit Service 97d2fb
/* Get the base address for the CU, fetches it when not yet set.
Packit Service 97d2fb
   This is used as initial base address for ranges and loclists.  */
Packit Service 97d2fb
Dwarf_Addr __libdw_cu_base_address (Dwarf_CU *cu);
Packit Service 97d2fb
Packit Service 97d2fb
/* Get the address base for the CU, fetches it when not yet set.  */
Packit Service 97d2fb
static inline Dwarf_Off
Packit Service 97d2fb
__libdw_cu_addr_base (Dwarf_CU *cu)
Packit Service 97d2fb
{
Packit Service 97d2fb
  if (cu->addr_base == (Dwarf_Off) -1)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      Dwarf_Die cu_die = CUDIE(cu);
Packit Service 97d2fb
      Dwarf_Attribute attr;
Packit Service 97d2fb
      Dwarf_Off offset = 0;
Packit Service 97d2fb
      if (dwarf_attr (&cu_die, DW_AT_GNU_addr_base, &attr) != NULL
Packit Service 97d2fb
	  || dwarf_attr (&cu_die, DW_AT_addr_base, &attr) != NULL)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  Dwarf_Word off;
Packit Service 97d2fb
	  if (dwarf_formudata (&attr, &off) == 0)
Packit Service 97d2fb
	    offset = off;
Packit Service 97d2fb
	}
Packit Service 97d2fb
      cu->addr_base = offset;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  return cu->addr_base;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
/* Gets the .debug_str_offsets base offset to use.  static inline to
Packit Service 97d2fb
   be shared between libdw and eu-readelf.  */
Packit Service 97d2fb
static inline Dwarf_Off
Packit Service 97d2fb
str_offsets_base_off (Dwarf *dbg, Dwarf_CU *cu)
Packit Service 97d2fb
{
Packit Service 97d2fb
  /* If we don't have a CU, then find and use the first one in the
Packit Service 97d2fb
     debug file (when we support .dwp files, we must actually find the
Packit Service 97d2fb
     one matching our "caller" - aka macro or line).  If we (now) have
Packit Service 97d2fb
     a cu and str_offsets_base attribute, just use that.  Otherwise
Packit Service 97d2fb
     use the first offset.  But we might have to parse the header
Packit Service 97d2fb
     first, but only if this is version 5.  Assume if all else fails,
Packit Service 97d2fb
     this is version 4, without header.  */
Packit Service 97d2fb
Packit Service 97d2fb
  if (cu == NULL && dbg != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      Dwarf_CU *first_cu;
Packit Service 97d2fb
      if (dwarf_get_units (dbg, NULL, &first_cu,
Packit Service 97d2fb
			   NULL, NULL, NULL, NULL) == 0)
Packit Service 97d2fb
	cu = first_cu;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  if (cu != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      if (cu->str_off_base == (Dwarf_Off) -1)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  Dwarf_Die cu_die = CUDIE(cu);
Packit Service 97d2fb
	  Dwarf_Attribute attr;
Packit Service 97d2fb
	  if (dwarf_attr (&cu_die, DW_AT_str_offsets_base, &attr) != NULL)
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      Dwarf_Word off;
Packit Service 97d2fb
	      if (dwarf_formudata (&attr, &off) == 0)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  cu->str_off_base = off;
Packit Service 97d2fb
		  return cu->str_off_base;
Packit Service 97d2fb
		}
Packit Service 97d2fb
	    }
Packit Service 97d2fb
	  /* For older DWARF simply assume zero (no header).  */
Packit Service 97d2fb
	  if (cu->version < 5)
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      cu->str_off_base = 0;
Packit Service 97d2fb
	      return cu->str_off_base;
Packit Service 97d2fb
	    }
Packit Service 97d2fb
Packit Service 97d2fb
	  if (dbg == NULL)
Packit Service 97d2fb
	    dbg = cu->dbg;
Packit Service 97d2fb
	}
Packit Service 97d2fb
      else
Packit Service 97d2fb
	return cu->str_off_base;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* No str_offsets_base attribute, we have to assume "zero".
Packit Service 97d2fb
     But there could be a header first.  */
Packit Service 97d2fb
  Dwarf_Off off = 0;
Packit Service 97d2fb
  if (dbg == NULL)
Packit Service 97d2fb
    goto no_header;
Packit Service 97d2fb
Packit Service 97d2fb
  Elf_Data *data =  dbg->sectiondata[IDX_debug_str_offsets];
Packit Service 97d2fb
  if (data == NULL)
Packit Service 97d2fb
    goto no_header;
Packit Service 97d2fb
Packit Service 97d2fb
  const unsigned char *start;
Packit Service 97d2fb
  const unsigned char *readp;
Packit Service 97d2fb
  const unsigned char *readendp;
Packit Service 97d2fb
  start = readp = (const unsigned char *) data->d_buf;
Packit Service 97d2fb
  readendp = (const unsigned char *) data->d_buf + data->d_size;
Packit Service 97d2fb
Packit Service 97d2fb
  uint64_t unit_length;
Packit Service 97d2fb
  uint16_t version;
Packit Service 97d2fb
Packit Service 97d2fb
  unit_length = read_4ubyte_unaligned_inc (dbg, readp);
Packit Service 97d2fb
  if (unlikely (unit_length == 0xffffffff))
Packit Service 97d2fb
    {
Packit Service 97d2fb
      if (unlikely (readendp - readp < 8))
Packit Service 97d2fb
	goto no_header;
Packit Service 97d2fb
      unit_length = read_8ubyte_unaligned_inc (dbg, readp);
Packit Service 97d2fb
      /* In theory the offset size could be different
Packit Service 97d2fb
	 between CU and str_offsets unit.  But we just
Packit Service 97d2fb
	 ignore that here. */
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* We need at least 2-bytes (version) + 2-bytes (padding) =
Packit Service 97d2fb
     4 bytes to complete the header.  And this unit cannot go
Packit Service 97d2fb
     beyond the section data.  */
Packit Service 97d2fb
  if (readendp - readp < 4
Packit Service 97d2fb
      || unit_length < 4
Packit Service 97d2fb
      || (uint64_t) (readendp - readp) < unit_length)
Packit Service 97d2fb
    goto no_header;
Packit Service 97d2fb
Packit Service 97d2fb
  version = read_2ubyte_unaligned_inc (dbg, readp);
Packit Service 97d2fb
  if (version != 5)
Packit Service 97d2fb
    goto no_header;
Packit Service 97d2fb
  /* padding */
Packit Service 97d2fb
  read_2ubyte_unaligned_inc (dbg, readp);
Packit Service 97d2fb
Packit Service 97d2fb
  off = (Dwarf_Off) (readp - start);
Packit Service 97d2fb
Packit Service 97d2fb
 no_header:
Packit Service 97d2fb
  if (cu != NULL)
Packit Service 97d2fb
    cu->str_off_base = off;
Packit Service 97d2fb
Packit Service 97d2fb
  return off;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Get the string offsets base for the CU, fetches it when not yet set.  */
Packit Service 97d2fb
static inline Dwarf_Off __libdw_cu_str_off_base (Dwarf_CU *cu)
Packit Service 97d2fb
{
Packit Service 97d2fb
  return str_offsets_base_off (NULL, cu);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Either a direct offset into .debug_ranges for version < 5, or the
Packit Service 97d2fb
   start of the offset table in .debug_rnglists for version > 5.  */
Packit Service 97d2fb
static inline Dwarf_Off
Packit Service 97d2fb
__libdw_cu_ranges_base (Dwarf_CU *cu)
Packit Service 97d2fb
{
Packit Service 97d2fb
  if (cu->ranges_base == (Dwarf_Off) -1)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      Dwarf_Off offset = 0;
Packit Service 97d2fb
      Dwarf_Die cu_die = CUDIE(cu);
Packit Service 97d2fb
      Dwarf_Attribute attr;
Packit Service 97d2fb
      if (cu->version < 5)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  if (dwarf_attr (&cu_die, DW_AT_GNU_ranges_base, &attr) != NULL)
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      Dwarf_Word off;
Packit Service 97d2fb
	      if (dwarf_formudata (&attr, &off) == 0)
Packit Service 97d2fb
		offset = off;
Packit Service 97d2fb
	    }
Packit Service 97d2fb
	}
Packit Service 97d2fb
      else
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  if (dwarf_attr (&cu_die, DW_AT_rnglists_base, &attr) != NULL)
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      Dwarf_Word off;
Packit Service 97d2fb
	      if (dwarf_formudata (&attr, &off) == 0)
Packit Service 97d2fb
		offset = off;
Packit Service 97d2fb
	    }
Packit Service 97d2fb
Packit Service 97d2fb
	  /* There wasn't an rnglists_base, if the Dwarf does have a
Packit Service 97d2fb
	     .debug_rnglists section, then it might be we need the
Packit Service 97d2fb
	     base after the first header. */
Packit Service 97d2fb
	  Elf_Data *data = cu->dbg->sectiondata[IDX_debug_rnglists];
Packit Service 97d2fb
	  if (offset == 0 && data != NULL)
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      Dwarf *dbg = cu->dbg;
Packit Service 97d2fb
	      const unsigned char *readp = data->d_buf;
Packit Service 97d2fb
	      const unsigned char *const dataend
Packit Service 97d2fb
		= (unsigned char *) data->d_buf + data->d_size;
Packit Service 97d2fb
Packit Service 97d2fb
	      uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
Packit Service 97d2fb
	      unsigned int offset_size = 4;
Packit Service 97d2fb
	      if (unlikely (unit_length == 0xffffffff))
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  if (unlikely (readp > dataend - 8))
Packit Service 97d2fb
		    goto no_header;
Packit Service 97d2fb
Packit Service 97d2fb
		  unit_length = read_8ubyte_unaligned_inc (dbg, readp);
Packit Service 97d2fb
		  offset_size = 8;
Packit Service 97d2fb
		}
Packit Service 97d2fb
Packit Service 97d2fb
	      if (readp > dataend - 8
Packit Service 97d2fb
		  || unit_length < 8
Packit Service 97d2fb
		  || unit_length > (uint64_t) (dataend - readp))
Packit Service 97d2fb
		goto no_header;
Packit Service 97d2fb
Packit Service 97d2fb
	      uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
Packit Service 97d2fb
	      if (version != 5)
Packit Service 97d2fb
		goto no_header;
Packit Service 97d2fb
Packit Service 97d2fb
	      uint8_t address_size = *readp++;
Packit Service 97d2fb
	      if (address_size != 4 && address_size != 8)
Packit Service 97d2fb
		goto no_header;
Packit Service 97d2fb
Packit Service 97d2fb
	      uint8_t segment_size = *readp++;
Packit Service 97d2fb
	      if (segment_size != 0)
Packit Service 97d2fb
		goto no_header;
Packit Service 97d2fb
Packit Service 97d2fb
	      uint32_t offset_entry_count;
Packit Service 97d2fb
	      offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
Packit Service 97d2fb
Packit Service 97d2fb
	      const unsigned char *offset_array_start = readp;
Packit Service 97d2fb
	      if (offset_entry_count <= 0)
Packit Service 97d2fb
		goto no_header;
Packit Service 97d2fb
Packit Service 97d2fb
	      uint64_t needed = offset_entry_count * offset_size;
Packit Service 97d2fb
	      if (unit_length - 8 < needed)
Packit Service 97d2fb
		goto no_header;
Packit Service 97d2fb
Packit Service 97d2fb
	      offset = (Dwarf_Off) (offset_array_start
Packit Service 97d2fb
				    - (unsigned char *) data->d_buf);
Packit Service 97d2fb
	    }
Packit Service 97d2fb
	}
Packit Service 97d2fb
    no_header:
Packit Service 97d2fb
      cu->ranges_base = offset;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  return cu->ranges_base;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* The start of the offset table in .debug_loclists for DWARF5.  */
Packit Service 97d2fb
static inline Dwarf_Off
Packit Service 97d2fb
__libdw_cu_locs_base (Dwarf_CU *cu)
Packit Service 97d2fb
{
Packit Service 97d2fb
  if (cu->locs_base == (Dwarf_Off) -1)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      Dwarf_Off offset = 0;
Packit Service 97d2fb
      Dwarf_Die cu_die = CUDIE(cu);
Packit Service 97d2fb
      Dwarf_Attribute attr;
Packit Service 97d2fb
      if (dwarf_attr (&cu_die, DW_AT_loclists_base, &attr) != NULL)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  Dwarf_Word off;
Packit Service 97d2fb
	  if (dwarf_formudata (&attr, &off) == 0)
Packit Service 97d2fb
	    offset = off;
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
      /* There wasn't an loclists_base, if the Dwarf does have a
Packit Service 97d2fb
	 .debug_loclists section, then it might be we need the
Packit Service 97d2fb
	 base after the first header. */
Packit Service 97d2fb
      Elf_Data *data = cu->dbg->sectiondata[IDX_debug_loclists];
Packit Service 97d2fb
      if (offset == 0 && data != NULL)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  Dwarf *dbg = cu->dbg;
Packit Service 97d2fb
	  const unsigned char *readp = data->d_buf;
Packit Service 97d2fb
	  const unsigned char *const dataend
Packit Service 97d2fb
	    = (unsigned char *) data->d_buf + data->d_size;
Packit Service 97d2fb
Packit Service 97d2fb
	  uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
Packit Service 97d2fb
	  unsigned int offset_size = 4;
Packit Service 97d2fb
	  if (unlikely (unit_length == 0xffffffff))
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      if (unlikely (readp > dataend - 8))
Packit Service 97d2fb
		goto no_header;
Packit Service 97d2fb
Packit Service 97d2fb
	      unit_length = read_8ubyte_unaligned_inc (dbg, readp);
Packit Service 97d2fb
	      offset_size = 8;
Packit Service 97d2fb
	    }
Packit Service 97d2fb
Packit Service 97d2fb
	  if (readp > dataend - 8
Packit Service 97d2fb
	      || unit_length < 8
Packit Service 97d2fb
	      || unit_length > (uint64_t) (dataend - readp))
Packit Service 97d2fb
	    goto no_header;
Packit Service 97d2fb
Packit Service 97d2fb
	  uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
Packit Service 97d2fb
	  if (version != 5)
Packit Service 97d2fb
	    goto no_header;
Packit Service 97d2fb
Packit Service 97d2fb
	  uint8_t address_size = *readp++;
Packit Service 97d2fb
	  if (address_size != 4 && address_size != 8)
Packit Service 97d2fb
	    goto no_header;
Packit Service 97d2fb
Packit Service 97d2fb
	  uint8_t segment_size = *readp++;
Packit Service 97d2fb
	  if (segment_size != 0)
Packit Service 97d2fb
	    goto no_header;
Packit Service 97d2fb
Packit Service 97d2fb
	  uint32_t offset_entry_count;
Packit Service 97d2fb
	  offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
Packit Service 97d2fb
Packit Service 97d2fb
	  const unsigned char *offset_array_start = readp;
Packit Service 97d2fb
	  if (offset_entry_count <= 0)
Packit Service 97d2fb
	    goto no_header;
Packit Service 97d2fb
Packit Service 97d2fb
	  uint64_t needed = offset_entry_count * offset_size;
Packit Service 97d2fb
	  if (unit_length - 8 < needed)
Packit Service 97d2fb
	    goto no_header;
Packit Service 97d2fb
Packit Service 97d2fb
	  offset = (Dwarf_Off) (offset_array_start
Packit Service 97d2fb
				- (unsigned char *) data->d_buf);
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
    no_header:
Packit Service 97d2fb
      cu->locs_base = offset;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  return cu->locs_base;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
/* Helper function for tsearch/tfind split_tree Dwarf.  */
Packit Service 97d2fb
int __libdw_finddbg_cb (const void *arg1, const void *arg2);
Packit Service 97d2fb
Packit Service 97d2fb
/* Link skeleton and split compile units.  */
Packit Service 97d2fb
static inline void
Packit Service 97d2fb
__libdw_link_skel_split (Dwarf_CU *skel, Dwarf_CU *split)
Packit Service 97d2fb
{
Packit Service 97d2fb
  skel->split = split;
Packit Service 97d2fb
  split->split = skel;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Get .debug_addr and addr_base greedy.
Packit Service 97d2fb
     We also need it for the fake addr cu.
Packit Service 97d2fb
     There is only one per split debug.  */
Packit Service 97d2fb
  Dwarf *dbg = skel->dbg;
Packit Service 97d2fb
  Dwarf *sdbg = split->dbg;
Packit Service 97d2fb
  if (sdbg->sectiondata[IDX_debug_addr] == NULL
Packit Service 97d2fb
      && dbg->sectiondata[IDX_debug_addr] != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      sdbg->sectiondata[IDX_debug_addr]
Packit Service 97d2fb
	= dbg->sectiondata[IDX_debug_addr];
Packit Service 97d2fb
      split->addr_base = __libdw_cu_addr_base (skel);
Packit Service 97d2fb
      sdbg->fake_addr_cu = dbg->fake_addr_cu;
Packit Service 97d2fb
    }
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Given an address index for a CU return the address.
Packit Service 97d2fb
   Returns -1 and sets libdw_errno if an error occurs.  */
Packit Service 97d2fb
int __libdw_addrx (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr);
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Helper function to set debugdir field in Dwarf, used from dwarf_begin_elf
Packit Service 97d2fb
   and libdwfl process_file.  */
Packit Service 97d2fb
char * __libdw_debugdir (int fd);
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Given the directory of a debug file, an absolute or relative dir
Packit Service 97d2fb
   to look in, and file returns a full path.
Packit Service 97d2fb
Packit Service 97d2fb
   If the file is absolute (starts with a /) a copy of file is returned.
Packit Service 97d2fb
   the file isn't absolute, but dir is absolute, then a path that is
Packit Service 97d2fb
   the concatenation of dir and file is returned.  If neither file,
Packit Service 97d2fb
   nor dir is absolute, the path will be constructed using dir (if not
Packit Service 97d2fb
   NULL) and file relative to the debugdir (if valid).
Packit Service 97d2fb
Packit Service 97d2fb
   The debugdir and the dir may be NULL (in which case they aren't used).
Packit Service 97d2fb
   If file is NULL, or no full path can be constructed NULL is returned.
Packit Service 97d2fb
Packit Service 97d2fb
   The caller is responsible for freeing the result if not NULL.  */
Packit Service 97d2fb
char * __libdw_filepath (const char *debugdir, const char *dir,
Packit Service 97d2fb
			 const char *file)
Packit Service 97d2fb
  internal_function;
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Aliases to avoid PLTs.  */
Packit Service 97d2fb
INTDECL (dwarf_aggregate_size)
Packit Service 97d2fb
INTDECL (dwarf_attr)
Packit Service 97d2fb
INTDECL (dwarf_attr_integrate)
Packit Service 97d2fb
INTDECL (dwarf_begin)
Packit Service 97d2fb
INTDECL (dwarf_begin_elf)
Packit Service 97d2fb
INTDECL (dwarf_child)
Packit Service 97d2fb
INTDECL (dwarf_default_lower_bound)
Packit Service 97d2fb
INTDECL (dwarf_dieoffset)
Packit Service 97d2fb
INTDECL (dwarf_diename)
Packit Service 97d2fb
INTDECL (dwarf_end)
Packit Service 97d2fb
INTDECL (dwarf_entrypc)
Packit Service 97d2fb
INTDECL (dwarf_errmsg)
Packit Service 97d2fb
INTDECL (dwarf_formaddr)
Packit Service 97d2fb
INTDECL (dwarf_formblock)
Packit Service 97d2fb
INTDECL (dwarf_formref_die)
Packit Service 97d2fb
INTDECL (dwarf_formsdata)
Packit Service 97d2fb
INTDECL (dwarf_formstring)
Packit Service 97d2fb
INTDECL (dwarf_formudata)
Packit Service 97d2fb
INTDECL (dwarf_getabbrevattr_data)
Packit Service 97d2fb
INTDECL (dwarf_getalt)
Packit Service 97d2fb
INTDECL (dwarf_getarange_addr)
Packit Service 97d2fb
INTDECL (dwarf_getarangeinfo)
Packit Service 97d2fb
INTDECL (dwarf_getaranges)
Packit Service 97d2fb
INTDECL (dwarf_getlocation_die)
Packit Service 97d2fb
INTDECL (dwarf_getsrcfiles)
Packit Service 97d2fb
INTDECL (dwarf_getsrclines)
Packit Service 97d2fb
INTDECL (dwarf_hasattr)
Packit Service 97d2fb
INTDECL (dwarf_haschildren)
Packit Service 97d2fb
INTDECL (dwarf_haspc)
Packit Service 97d2fb
INTDECL (dwarf_highpc)
Packit Service 97d2fb
INTDECL (dwarf_lowpc)
Packit Service 97d2fb
INTDECL (dwarf_nextcu)
Packit Service 97d2fb
INTDECL (dwarf_next_unit)
Packit Service 97d2fb
INTDECL (dwarf_offdie)
Packit Service 97d2fb
INTDECL (dwarf_peel_type)
Packit Service 97d2fb
INTDECL (dwarf_ranges)
Packit Service 97d2fb
INTDECL (dwarf_setalt)
Packit Service 97d2fb
INTDECL (dwarf_siblingof)
Packit Service 97d2fb
INTDECL (dwarf_srclang)
Packit Service 97d2fb
INTDECL (dwarf_tag)
Packit Service 97d2fb
Packit Service 97d2fb
#endif	/* libdwP.h */