Home | History | Annotate | Download | only in libdw
      1 /* Internal definitions for libdwarf.
      2    Copyright (C) 2002-2011, 2013, 2014 Red Hat, Inc.
      3    This file is part of elfutils.
      4    Written by Ulrich Drepper <drepper (at) redhat.com>, 2002.
      5 
      6    This file is free software; you can redistribute it and/or modify
      7    it under the terms of either
      8 
      9      * the GNU Lesser General Public License as published by the Free
     10        Software Foundation; either version 3 of the License, or (at
     11        your option) any later version
     12 
     13    or
     14 
     15      * the GNU General Public License as published by the Free
     16        Software Foundation; either version 2 of the License, or (at
     17        your option) any later version
     18 
     19    or both in parallel, as here.
     20 
     21    elfutils is distributed in the hope that it will be useful, but
     22    WITHOUT ANY WARRANTY; without even the implied warranty of
     23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     24    General Public License for more details.
     25 
     26    You should have received copies of the GNU General Public License and
     27    the GNU Lesser General Public License along with this program.  If
     28    not, see <http://www.gnu.org/licenses/>.  */
     29 
     30 #ifndef _LIBDWP_H
     31 #define _LIBDWP_H 1
     32 
     33 #include <libintl.h>
     34 #include <stdbool.h>
     35 
     36 #include <libdw.h>
     37 #include <dwarf.h>
     38 
     39 
     40 /* gettext helper macros.  */
     41 #define _(Str) dgettext ("elfutils", Str)
     42 
     43 
     44 /* Known location expressions already decoded.  */
     45 struct loc_s
     46 {
     47   void *addr;
     48   Dwarf_Op *loc;
     49   size_t nloc;
     50 };
     51 
     52 /* Known DW_OP_implicit_value blocks already decoded.
     53    This overlaps struct loc_s exactly, but only the
     54    first member really has to match.  */
     55 struct loc_block_s
     56 {
     57   void *addr;
     58   unsigned char *data;
     59   size_t length;
     60 };
     61 
     62 /* Already decoded .debug_line units.  */
     63 struct files_lines_s
     64 {
     65   Dwarf_Off debug_line_offset;
     66   Dwarf_Files *files;
     67   Dwarf_Lines *lines;
     68 };
     69 
     70 /* Valid indeces for the section data.  */
     71 enum
     72   {
     73     IDX_debug_info = 0,
     74     IDX_debug_types,
     75     IDX_debug_abbrev,
     76     IDX_debug_aranges,
     77     IDX_debug_line,
     78     IDX_debug_frame,
     79     IDX_debug_loc,
     80     IDX_debug_pubnames,
     81     IDX_debug_str,
     82     IDX_debug_macinfo,
     83     IDX_debug_macro,
     84     IDX_debug_ranges,
     85     IDX_gnu_debugaltlink,
     86     IDX_last
     87   };
     88 
     89 
     90 /* Error values.  */
     91 enum
     92 {
     93   DWARF_E_NOERROR = 0,
     94   DWARF_E_UNKNOWN_ERROR,
     95   DWARF_E_INVALID_ACCESS,
     96   DWARF_E_NO_REGFILE,
     97   DWARF_E_IO_ERROR,
     98   DWARF_E_INVALID_ELF,
     99   DWARF_E_NO_DWARF,
    100   DWARF_E_NOELF,
    101   DWARF_E_GETEHDR_ERROR,
    102   DWARF_E_NOMEM,
    103   DWARF_E_UNIMPL,
    104   DWARF_E_INVALID_CMD,
    105   DWARF_E_INVALID_VERSION,
    106   DWARF_E_INVALID_FILE,
    107   DWARF_E_NO_ENTRY,
    108   DWARF_E_INVALID_DWARF,
    109   DWARF_E_NO_STRING,
    110   DWARF_E_NO_ADDR,
    111   DWARF_E_NO_CONSTANT,
    112   DWARF_E_NO_REFERENCE,
    113   DWARF_E_INVALID_REFERENCE,
    114   DWARF_E_NO_DEBUG_LINE,
    115   DWARF_E_INVALID_DEBUG_LINE,
    116   DWARF_E_TOO_BIG,
    117   DWARF_E_VERSION,
    118   DWARF_E_INVALID_DIR_IDX,
    119   DWARF_E_ADDR_OUTOFRANGE,
    120   DWARF_E_NO_LOCLIST,
    121   DWARF_E_NO_BLOCK,
    122   DWARF_E_INVALID_LINE_IDX,
    123   DWARF_E_INVALID_ARANGE_IDX,
    124   DWARF_E_NO_MATCH,
    125   DWARF_E_NO_FLAG,
    126   DWARF_E_INVALID_OFFSET,
    127   DWARF_E_NO_DEBUG_RANGES,
    128   DWARF_E_INVALID_CFI,
    129   DWARF_E_NO_ALT_DEBUGLINK,
    130   DWARF_E_INVALID_OPCODE,
    131 };
    132 
    133 
    134 #include "dwarf_sig8_hash.h"
    135 
    136 /* This is the structure representing the debugging state.  */
    137 struct Dwarf
    138 {
    139   /* The underlying ELF file.  */
    140   Elf *elf;
    141 
    142   /* dwz alternate DWARF file.  */
    143   Dwarf *alt_dwarf;
    144 
    145   /* The section data.  */
    146   Elf_Data *sectiondata[IDX_last];
    147 
    148 #if USE_ZLIB
    149   /* The 1 << N bit is set if sectiondata[N] is malloc'd decompressed data.  */
    150   unsigned int sectiondata_gzip_mask:IDX_last;
    151 #endif
    152 
    153   /* True if the file has a byte order different from the host.  */
    154   bool other_byte_order;
    155 
    156   /* If true, we allocated the ELF descriptor ourselves.  */
    157   bool free_elf;
    158 
    159   /* Information for traversing the .debug_pubnames section.  This is
    160      an array and separately allocated with malloc.  */
    161   struct pubnames_s
    162   {
    163     Dwarf_Off cu_offset;
    164     Dwarf_Off set_start;
    165     unsigned int cu_header_size;
    166     int address_len;
    167   } *pubnames_sets;
    168   size_t pubnames_nsets;
    169 
    170   /* Search tree for the CUs.  */
    171   void *cu_tree;
    172   Dwarf_Off next_cu_offset;
    173 
    174   /* Search tree and sig8 hash table for .debug_types type units.  */
    175   void *tu_tree;
    176   Dwarf_Off next_tu_offset;
    177   Dwarf_Sig8_Hash sig8_hash;
    178 
    179   /* Search tree for .debug_macro operator tables.  */
    180   void *macro_ops;
    181 
    182   /* Search tree for decoded .debug_line units.  */
    183   void *files_lines;
    184 
    185   /* Address ranges.  */
    186   Dwarf_Aranges *aranges;
    187 
    188   /* Cached info from the CFI section.  */
    189   struct Dwarf_CFI_s *cfi;
    190 
    191   /* Fake loc CU.  Used when synthesizing attributes for Dwarf_Ops that
    192      came from a location list entry in dwarf_getlocation_attr.  */
    193   struct Dwarf_CU *fake_loc_cu;
    194 
    195   /* Internal memory handling.  This is basically a simplified
    196      reimplementation of obstacks.  Unfortunately the standard obstack
    197      implementation is not usable in libraries.  */
    198   struct libdw_memblock
    199   {
    200     size_t size;
    201     size_t remaining;
    202     struct libdw_memblock *prev;
    203     char mem[0];
    204   } *mem_tail;
    205 
    206   /* Default size of allocated memory blocks.  */
    207   size_t mem_default_size;
    208 
    209   /* Registered OOM handler.  */
    210   Dwarf_OOM oom_handler;
    211 };
    212 
    213 
    214 /* Abbreviation representation.  */
    215 struct Dwarf_Abbrev
    216 {
    217   Dwarf_Off offset;
    218   unsigned char *attrp;
    219   unsigned int attrcnt;
    220   unsigned int code;
    221   unsigned int tag;
    222   bool has_children;
    223 };
    224 
    225 #include "dwarf_abbrev_hash.h"
    226 
    227 
    228 /* Files in line information records.  */
    229 struct Dwarf_Files_s
    230   {
    231     unsigned int ndirs;
    232     unsigned int nfiles;
    233     struct Dwarf_Fileinfo_s
    234     {
    235       char *name;
    236       Dwarf_Word mtime;
    237       Dwarf_Word length;
    238     } info[0];
    239     /* nfiles of those, followed by char *[ndirs].  */
    240   };
    241 typedef struct Dwarf_Fileinfo_s Dwarf_Fileinfo;
    242 
    243 
    244 /* Representation of a row in the line table.  */
    245 
    246 struct Dwarf_Line_s
    247 {
    248   Dwarf_Files *files;
    249 
    250   Dwarf_Addr addr;
    251   unsigned int file;
    252   int line;
    253   unsigned short int column;
    254   unsigned int is_stmt:1;
    255   unsigned int basic_block:1;
    256   unsigned int end_sequence:1;
    257   unsigned int prologue_end:1;
    258   unsigned int epilogue_begin:1;
    259   /* The remaining bit fields are not flags, but hold values presumed to be
    260      small.  All the flags and other bit fields should add up to 48 bits
    261      to give the whole struct a nice round size.  */
    262   unsigned int op_index:8;
    263   unsigned int isa:8;
    264   unsigned int discriminator:24;
    265 };
    266 
    267 struct Dwarf_Lines_s
    268 {
    269   size_t nlines;
    270   struct Dwarf_Line_s info[0];
    271 };
    272 
    273 /* Representation of address ranges.  */
    274 struct Dwarf_Aranges_s
    275 {
    276   Dwarf *dbg;
    277   size_t naranges;
    278 
    279   struct Dwarf_Arange_s
    280   {
    281     Dwarf_Addr addr;
    282     Dwarf_Word length;
    283     Dwarf_Off offset;
    284   } info[0];
    285 };
    286 
    287 
    288 /* CU representation.  */
    289 struct Dwarf_CU
    290 {
    291   Dwarf *dbg;
    292   Dwarf_Off start;
    293   Dwarf_Off end;
    294   uint8_t address_size;
    295   uint8_t offset_size;
    296   uint16_t version;
    297 
    298   /* Zero if this is a normal CU.  Nonzero if it is a type unit.  */
    299   size_t type_offset;
    300   uint64_t type_sig8;
    301 
    302   /* Hash table for the abbreviations.  */
    303   Dwarf_Abbrev_Hash abbrev_hash;
    304   /* Offset of the first abbreviation.  */
    305   size_t orig_abbrev_offset;
    306   /* Offset past last read abbreviation.  */
    307   size_t last_abbrev_offset;
    308 
    309   /* The srcline information.  */
    310   Dwarf_Lines *lines;
    311 
    312   /* The source file information.  */
    313   Dwarf_Files *files;
    314 
    315   /* Known location lists.  */
    316   void *locs;
    317 
    318   /* Memory boundaries of this CU.  */
    319   void *startp;
    320   void *endp;
    321 };
    322 
    323 /* Compute the offset of a CU's first DIE from its offset.  This
    324    is either:
    325         LEN       VER     OFFSET    ADDR
    326       4-bytes + 2-bytes + 4-bytes + 1-byte  for 32-bit dwarf
    327      12-bytes + 2-bytes + 8-bytes + 1-byte  for 64-bit dwarf
    328    or in .debug_types, 			     SIGNATURE TYPE-OFFSET
    329       4-bytes + 2-bytes + 4-bytes + 1-byte + 8-bytes + 4-bytes  for 32-bit
    330      12-bytes + 2-bytes + 8-bytes + 1-byte + 8-bytes + 8-bytes  for 64-bit
    331 
    332    Note the trick in the computation.  If the offset_size is 4
    333    the '- 4' term changes the '3 *' into a '2 *'.  If the
    334    offset_size is 8 it accounts for the 4-byte escape value
    335    used at the start of the length.  */
    336 #define DIE_OFFSET_FROM_CU_OFFSET(cu_offset, offset_size, type_unit)	\
    337   ((type_unit) ? ((cu_offset) + 4 * (offset_size) - 4 + 3 + 8)		\
    338    : ((cu_offset) + 3 * (offset_size) - 4 + 3))
    339 
    340 #define CUDIE(fromcu)							      \
    341   ((Dwarf_Die)								      \
    342    {									      \
    343      .cu = (fromcu),							      \
    344      .addr = ((char *) fromcu->dbg->sectiondata[cu_sec_idx (fromcu)]->d_buf   \
    345 	      + DIE_OFFSET_FROM_CU_OFFSET ((fromcu)->start,		      \
    346 					   (fromcu)->offset_size,	      \
    347 					   (fromcu)->type_offset != 0))	      \
    348    })									      \
    349 
    350 
    351 /* Prototype of a single .debug_macro operator.  */
    352 typedef struct
    353 {
    354   Dwarf_Word nforms;
    355   unsigned char const *forms;
    356 } Dwarf_Macro_Op_Proto;
    357 
    358 /* Prototype table.  */
    359 typedef struct
    360 {
    361   /* Offset of .debug_macro section.  */
    362   Dwarf_Off offset;
    363 
    364   /* Offset of associated .debug_line section.  */
    365   Dwarf_Off line_offset;
    366 
    367   /* The source file information.  */
    368   Dwarf_Files *files;
    369 
    370   /* If this macro unit was opened through dwarf_getmacros or
    371      dwarf_getmacros_die, this caches value of DW_AT_comp_dir, if
    372      present.  */
    373   const char *comp_dir;
    374 
    375   /* Header length.  */
    376   Dwarf_Half header_len;
    377 
    378   uint16_t version;
    379   bool is_64bit;
    380   uint8_t sec_index;	/* IDX_debug_macro or IDX_debug_macinfo.  */
    381 
    382   /* Shows where in TABLE each opcode is defined.  Since opcode 0 is
    383      never used, it stores index of opcode X in X-1'th element.  The
    384      value of 0xff means not stored at all.  */
    385   unsigned char opcodes[255];
    386 
    387   /* Individual opcode prototypes.  */
    388   Dwarf_Macro_Op_Proto table[];
    389 } Dwarf_Macro_Op_Table;
    390 
    391 struct Dwarf_Macro_s
    392 {
    393   Dwarf_Macro_Op_Table *table;
    394   Dwarf_Attribute *attributes;
    395   uint8_t opcode;
    396 };
    397 
    398 static inline Dwarf_Word
    399 libdw_macro_nforms (Dwarf_Macro *macro)
    400 {
    401   return macro->table->table[macro->table->opcodes[macro->opcode - 1]].nforms;
    402 }
    403 
    404 /* We have to include the file at this point because the inline
    405    functions access internals of the Dwarf structure.  */
    406 #include "memory-access.h"
    407 
    408 
    409 /* Set error value.  */
    410 extern void __libdw_seterrno (int value) internal_function;
    411 
    412 
    413 /* Memory handling, the easy parts.  This macro does not do any locking.  */
    414 #define libdw_alloc(dbg, type, tsize, cnt) \
    415   ({ struct libdw_memblock *_tail = (dbg)->mem_tail;			      \
    416      size_t _required = (tsize) * (cnt);				      \
    417      type *_result = (type *) (_tail->mem + (_tail->size - _tail->remaining));\
    418      size_t _padding = ((__alignof (type)				      \
    419 			 - ((uintptr_t) _result & (__alignof (type) - 1)))    \
    420 			& (__alignof (type) - 1));			      \
    421      if (unlikely (_tail->remaining < _required + _padding))		      \
    422        _result = (type *) __libdw_allocate (dbg, _required, __alignof (type));\
    423      else								      \
    424        {								      \
    425 	 _required += _padding;						      \
    426 	 _result = (type *) ((char *) _result + _padding);		      \
    427 	 _tail->remaining -= _required;					      \
    428        }								      \
    429      _result; })
    430 
    431 #define libdw_typed_alloc(dbg, type) \
    432   libdw_alloc (dbg, type, sizeof (type), 1)
    433 
    434 /* Callback to allocate more.  */
    435 extern void *__libdw_allocate (Dwarf *dbg, size_t minsize, size_t align)
    436      __attribute__ ((__malloc__)) __nonnull_attribute__ (1);
    437 
    438 /* Default OOM handler.  */
    439 extern void __libdw_oom (void) __attribute ((noreturn, visibility ("hidden")));
    440 
    441 #if USE_ZLIB
    442 extern void __libdw_free_zdata (Dwarf *dwarf) internal_function;
    443 #else
    444 # define __libdw_free_zdata(dwarf)	((void) (dwarf))
    445 #endif
    446 
    447 /* Allocate the internal data for a unit not seen before.  */
    448 extern struct Dwarf_CU *__libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
    449      __nonnull_attribute__ (1) internal_function;
    450 
    451 /* Find CU for given offset.  */
    452 extern struct Dwarf_CU *__libdw_findcu (Dwarf *dbg, Dwarf_Off offset, bool tu)
    453      __nonnull_attribute__ (1) internal_function;
    454 
    455 /* Get abbreviation with given code.  */
    456 extern Dwarf_Abbrev *__libdw_findabbrev (struct Dwarf_CU *cu,
    457 					 unsigned int code)
    458      __nonnull_attribute__ (1) internal_function;
    459 
    460 /* Get abbreviation at given offset.  */
    461 extern Dwarf_Abbrev *__libdw_getabbrev (Dwarf *dbg, struct Dwarf_CU *cu,
    462 					Dwarf_Off offset, size_t *lengthp,
    463 					Dwarf_Abbrev *result)
    464      __nonnull_attribute__ (1) internal_function;
    465 
    466 /* Get abbreviation of given DIE, and optionally set *READP to the DIE memory
    467    just past the abbreviation code.  */
    468 static inline Dwarf_Abbrev *
    469 __nonnull_attribute__ (1)
    470 __libdw_dieabbrev (Dwarf_Die *die, const unsigned char **readp)
    471 {
    472   /* Do we need to get the abbreviation, or need to read after the code?  */
    473   if (die->abbrev == NULL || readp != NULL)
    474     {
    475       /* Get the abbreviation code.  */
    476       unsigned int code;
    477       const unsigned char *addr = die->addr;
    478       get_uleb128 (code, addr, die->cu->endp);
    479       if (readp != NULL)
    480 	*readp = addr;
    481 
    482       /* Find the abbreviation.  */
    483       if (die->abbrev == NULL)
    484 	die->abbrev = __libdw_findabbrev (die->cu, code);
    485     }
    486   return die->abbrev;
    487 }
    488 
    489 /* Helper functions for form handling.  */
    490 extern size_t __libdw_form_val_compute_len (struct Dwarf_CU *cu,
    491 					    unsigned int form,
    492 					    const unsigned char *valp)
    493      __nonnull_attribute__ (1, 3) internal_function;
    494 
    495 /* Find the length of a form attribute.  */
    496 static inline size_t
    497 __nonnull_attribute__ (1, 3)
    498 __libdw_form_val_len (struct Dwarf_CU *cu, unsigned int form,
    499 		      const unsigned char *valp)
    500 {
    501   /* Small lookup table of forms with fixed lengths.  Absent indexes are
    502      initialized 0, so any truly desired 0 is set to 0x80 and masked.  */
    503   static const uint8_t form_lengths[] =
    504     {
    505       [DW_FORM_flag_present] = 0x80,
    506       [DW_FORM_data1] = 1, [DW_FORM_ref1] = 1, [DW_FORM_flag] = 1,
    507       [DW_FORM_data2] = 2, [DW_FORM_ref2] = 2,
    508       [DW_FORM_data4] = 4, [DW_FORM_ref4] = 4,
    509       [DW_FORM_data8] = 8, [DW_FORM_ref8] = 8, [DW_FORM_ref_sig8] = 8,
    510     };
    511 
    512   /* Return immediately for forms with fixed lengths.  */
    513   if (form < sizeof form_lengths / sizeof form_lengths[0])
    514     {
    515       uint8_t len = form_lengths[form];
    516       if (len != 0)
    517 	{
    518 	  const unsigned char *endp = cu->endp;
    519 	  len &= 0x7f; /* Mask to allow 0x80 -> 0.  */
    520 	  if (unlikely (len > (size_t) (endp - valp)))
    521 	    {
    522 	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
    523 	      return -1;
    524 	    }
    525 	  return len;
    526 	}
    527     }
    528 
    529   /* Other forms require some computation.  */
    530   return __libdw_form_val_compute_len (cu, form, valp);
    531 }
    532 
    533 /* Helper function for DW_FORM_ref* handling.  */
    534 extern int __libdw_formref (Dwarf_Attribute *attr, Dwarf_Off *return_offset)
    535      __nonnull_attribute__ (1, 2) internal_function;
    536 
    537 
    538 /* Helper function to locate attribute.  */
    539 extern unsigned char *__libdw_find_attr (Dwarf_Die *die,
    540 					 unsigned int search_name,
    541 					 unsigned int *codep,
    542 					 unsigned int *formp)
    543      __nonnull_attribute__ (1) internal_function;
    544 
    545 /* Helper function to access integer attribute.  */
    546 extern int __libdw_attr_intval (Dwarf_Die *die, int *valp, int attval)
    547      __nonnull_attribute__ (1, 2) internal_function;
    548 
    549 /* Helper function to walk scopes.  */
    550 struct Dwarf_Die_Chain
    551 {
    552   Dwarf_Die die;
    553   struct Dwarf_Die_Chain *parent;
    554   bool prune;			/* The PREVISIT function can set this.  */
    555 };
    556 extern int __libdw_visit_scopes (unsigned int depth,
    557 				 struct Dwarf_Die_Chain *root,
    558 				 int (*previsit) (unsigned int depth,
    559 						  struct Dwarf_Die_Chain *,
    560 						  void *arg),
    561 				 int (*postvisit) (unsigned int depth,
    562 						   struct Dwarf_Die_Chain *,
    563 						   void *arg),
    564 				 void *arg)
    565   __nonnull_attribute__ (2, 3) internal_function;
    566 
    567 /* Parse a DWARF Dwarf_Block into an array of Dwarf_Op's,
    568    and cache the result (via tsearch).  */
    569 extern int __libdw_intern_expression (Dwarf *dbg,
    570 				      bool other_byte_order,
    571 				      unsigned int address_size,
    572 				      unsigned int ref_size,
    573 				      void **cache, const Dwarf_Block *block,
    574 				      bool cfap, bool valuep,
    575 				      Dwarf_Op **llbuf, size_t *listlen,
    576 				      int sec_index)
    577   __nonnull_attribute__ (5, 6, 9, 10) internal_function;
    578 
    579 extern Dwarf_Die *__libdw_offdie (Dwarf *dbg, Dwarf_Off offset,
    580 				  Dwarf_Die *result, bool debug_types)
    581   internal_function;
    582 
    583 
    584 /* Return error code of last failing function call.  This value is kept
    585    separately for each thread.  */
    586 extern int __dwarf_errno_internal (void);
    587 
    588 
    589 /* Reader hooks.  */
    590 
    591 /* Relocation hooks return -1 on error (in that case the error code
    592    must already have been set), 0 if there is no relocation and 1 if a
    593    relocation was present.*/
    594 
    595 static inline int
    596 __libdw_relocate_address (Dwarf *dbg __attribute__ ((unused)),
    597 			  int sec_index __attribute__ ((unused)),
    598 			  const void *addr __attribute__ ((unused)),
    599 			  int width __attribute__ ((unused)),
    600 			  Dwarf_Addr *val __attribute__ ((unused)))
    601 {
    602   return 0;
    603 }
    604 
    605 static inline int
    606 __libdw_relocate_offset (Dwarf *dbg __attribute__ ((unused)),
    607 			 int sec_index __attribute__ ((unused)),
    608 			 const void *addr __attribute__ ((unused)),
    609 			 int width __attribute__ ((unused)),
    610 			 Dwarf_Off *val __attribute__ ((unused)))
    611 {
    612   return 0;
    613 }
    614 
    615 static inline Elf_Data *
    616 __libdw_checked_get_data (Dwarf *dbg, int sec_index)
    617 {
    618   Elf_Data *data = dbg->sectiondata[sec_index];
    619   if (unlikely (data == NULL)
    620       || unlikely (data->d_buf == NULL))
    621     {
    622       __libdw_seterrno (DWARF_E_INVALID_DWARF);
    623       return NULL;
    624     }
    625   return data;
    626 }
    627 
    628 static inline int
    629 __libdw_offset_in_section (Dwarf *dbg, int sec_index,
    630 			   Dwarf_Off offset, size_t size)
    631 {
    632   Elf_Data *data = __libdw_checked_get_data (dbg, sec_index);
    633   if (data == NULL)
    634     return -1;
    635   if (unlikely (offset > data->d_size)
    636       || unlikely (data->d_size - offset < size))
    637     {
    638       __libdw_seterrno (DWARF_E_INVALID_OFFSET);
    639       return -1;
    640     }
    641 
    642   return 0;
    643 }
    644 
    645 static inline bool
    646 __libdw_in_section (Dwarf *dbg, int sec_index,
    647 		    const void *addr, size_t size)
    648 {
    649   Elf_Data *data = __libdw_checked_get_data (dbg, sec_index);
    650   if (data == NULL)
    651     return false;
    652   if (unlikely (addr < data->d_buf)
    653       || unlikely (data->d_size - (addr - data->d_buf) < size))
    654     {
    655       __libdw_seterrno (DWARF_E_INVALID_OFFSET);
    656       return false;
    657     }
    658 
    659   return true;
    660 }
    661 
    662 #define READ_AND_RELOCATE(RELOC_HOOK, VAL)				\
    663   ({									\
    664     if (!__libdw_in_section (dbg, sec_index, addr, width))		\
    665       return -1;							\
    666 									\
    667     const unsigned char *orig_addr = addr;				\
    668     if (width == 4)							\
    669       VAL = read_4ubyte_unaligned_inc (dbg, addr);			\
    670     else								\
    671       VAL = read_8ubyte_unaligned_inc (dbg, addr);			\
    672 									\
    673     int status = RELOC_HOOK (dbg, sec_index, orig_addr, width, &VAL);	\
    674     if (status < 0)							\
    675       return status;							\
    676     status > 0;								\
    677    })
    678 
    679 static inline int
    680 __libdw_read_address_inc (Dwarf *dbg,
    681 			  int sec_index, const unsigned char **addrp,
    682 			  int width, Dwarf_Addr *ret)
    683 {
    684   const unsigned char *addr = *addrp;
    685   READ_AND_RELOCATE (__libdw_relocate_address, (*ret));
    686   *addrp = addr;
    687   return 0;
    688 }
    689 
    690 static inline int
    691 __libdw_read_address (Dwarf *dbg,
    692 		      int sec_index, const unsigned char *addr,
    693 		      int width, Dwarf_Addr *ret)
    694 {
    695   READ_AND_RELOCATE (__libdw_relocate_address, (*ret));
    696   return 0;
    697 }
    698 
    699 static inline int
    700 __libdw_read_offset_inc (Dwarf *dbg,
    701 			 int sec_index, const unsigned char **addrp,
    702 			 int width, Dwarf_Off *ret, int sec_ret,
    703 			 size_t size)
    704 {
    705   const unsigned char *addr = *addrp;
    706   READ_AND_RELOCATE (__libdw_relocate_offset, (*ret));
    707   *addrp = addr;
    708   return __libdw_offset_in_section (dbg, sec_ret, *ret, size);
    709 }
    710 
    711 static inline int
    712 __libdw_read_offset (Dwarf *dbg, Dwarf *dbg_ret,
    713 		     int sec_index, const unsigned char *addr,
    714 		     int width, Dwarf_Off *ret, int sec_ret,
    715 		     size_t size)
    716 {
    717   READ_AND_RELOCATE (__libdw_relocate_offset, (*ret));
    718   return __libdw_offset_in_section (dbg_ret, sec_ret, *ret, size);
    719 }
    720 
    721 static inline size_t
    722 cu_sec_idx (struct Dwarf_CU *cu)
    723 {
    724   return cu->type_offset == 0 ? IDX_debug_info : IDX_debug_types;
    725 }
    726 
    727 /* Read up begin/end pair and increment read pointer.
    728     - If it's normal range record, set up *BEGINP and *ENDP and return 0.
    729     - If it's base address selection record, set up *BASEP and return 1.
    730     - If it's end of rangelist, don't set anything and return 2
    731     - If an error occurs, don't set anything and return <0.  */
    732 int __libdw_read_begin_end_pair_inc (Dwarf *dbg, int sec_index,
    733 				     unsigned char **addr, int width,
    734 				     Dwarf_Addr *beginp, Dwarf_Addr *endp,
    735 				     Dwarf_Addr *basep)
    736   internal_function;
    737 
    738 unsigned char * __libdw_formptr (Dwarf_Attribute *attr, int sec_index,
    739 				 int err_nodata, unsigned char **endpp,
    740 				 Dwarf_Off *offsetp)
    741   internal_function;
    742 
    743 /* Fills in the given attribute to point at an empty location expression.  */
    744 void __libdw_empty_loc_attr (Dwarf_Attribute *attr)
    745   internal_function;
    746 
    747 /* Load .debug_line unit at DEBUG_LINE_OFFSET.  COMP_DIR is a value of
    748    DW_AT_comp_dir or NULL if that attribute is not available.  Caches
    749    the loaded unit and optionally set *LINESP and/or *FILESP (if not
    750    NULL) with loaded information.  Returns 0 for success or a negative
    751    value for failure.  */
    752 int __libdw_getsrclines (Dwarf *dbg, Dwarf_Off debug_line_offset,
    753 			 const char *comp_dir, unsigned address_size,
    754 			 Dwarf_Lines **linesp, Dwarf_Files **filesp)
    755   internal_function
    756   __nonnull_attribute__ (1);
    757 
    758 /* Load and return value of DW_AT_comp_dir from CUDIE.  */
    759 const char *__libdw_getcompdir (Dwarf_Die *cudie);
    760 
    761 
    762 /* Aliases to avoid PLTs.  */
    763 INTDECL (dwarf_aggregate_size)
    764 INTDECL (dwarf_attr)
    765 INTDECL (dwarf_attr_integrate)
    766 INTDECL (dwarf_begin)
    767 INTDECL (dwarf_begin_elf)
    768 INTDECL (dwarf_child)
    769 INTDECL (dwarf_dieoffset)
    770 INTDECL (dwarf_diename)
    771 INTDECL (dwarf_end)
    772 INTDECL (dwarf_entrypc)
    773 INTDECL (dwarf_errmsg)
    774 INTDECL (dwarf_formaddr)
    775 INTDECL (dwarf_formblock)
    776 INTDECL (dwarf_formref_die)
    777 INTDECL (dwarf_formsdata)
    778 INTDECL (dwarf_formstring)
    779 INTDECL (dwarf_formudata)
    780 INTDECL (dwarf_getalt)
    781 INTDECL (dwarf_getarange_addr)
    782 INTDECL (dwarf_getarangeinfo)
    783 INTDECL (dwarf_getaranges)
    784 INTDECL (dwarf_getlocation_die)
    785 INTDECL (dwarf_getsrcfiles)
    786 INTDECL (dwarf_getsrclines)
    787 INTDECL (dwarf_hasattr)
    788 INTDECL (dwarf_haschildren)
    789 INTDECL (dwarf_haspc)
    790 INTDECL (dwarf_highpc)
    791 INTDECL (dwarf_lowpc)
    792 INTDECL (dwarf_nextcu)
    793 INTDECL (dwarf_next_unit)
    794 INTDECL (dwarf_offdie)
    795 INTDECL (dwarf_peel_type)
    796 INTDECL (dwarf_ranges)
    797 INTDECL (dwarf_setalt)
    798 INTDECL (dwarf_siblingof)
    799 INTDECL (dwarf_srclang)
    800 INTDECL (dwarf_tag)
    801 
    802 #endif	/* libdwP.h */
    803