summaryrefslogtreecommitdiff
path: root/elfutils/libdw/libdwP.h
diff options
context:
space:
mode:
Diffstat (limited to 'elfutils/libdw/libdwP.h')
-rw-r--r--elfutils/libdw/libdwP.h181
1 files changed, 178 insertions, 3 deletions
diff --git a/elfutils/libdw/libdwP.h b/elfutils/libdw/libdwP.h
index 1d5a9b27..0284580f 100644
--- a/elfutils/libdw/libdwP.h
+++ b/elfutils/libdw/libdwP.h
@@ -76,6 +76,16 @@ struct loc_s
size_t nloc;
};
+/* Known DW_OP_implicit_value blocks already decoded.
+ This overlaps struct loc_s exactly, but only the
+ first member really has to match. */
+struct loc_block_s
+{
+ void *addr;
+ unsigned char *data;
+ size_t length;
+};
+
/* Valid indeces for the section data. */
enum
{
@@ -84,7 +94,6 @@ enum
IDX_debug_aranges,
IDX_debug_line,
IDX_debug_frame,
- IDX_eh_frame,
IDX_debug_loc,
IDX_debug_pubnames,
IDX_debug_str,
@@ -136,6 +145,7 @@ enum
DWARF_E_NO_FLAG,
DWARF_E_INVALID_OFFSET,
DWARF_E_NO_DEBUG_RANGES,
+ DWARF_E_INVALID_CFI,
};
@@ -172,6 +182,9 @@ struct Dwarf
/* Address ranges. */
Dwarf_Aranges *aranges;
+ /* Cached info from the CFI section. */
+ struct Dwarf_CFI_s *cfi;
+
/* Internal memory handling. This is basically a simplified
reimplementation of obstacks. Unfortunately the standard obstack
implementation is not usable in libraries. */
@@ -226,6 +239,8 @@ typedef struct Dwarf_Fileinfo_s Dwarf_Fileinfo;
struct Dwarf_Line_s
{
+ Dwarf_Files *files;
+
Dwarf_Addr addr;
unsigned int file;
int line;
@@ -235,8 +250,6 @@ struct Dwarf_Line_s
unsigned int end_sequence:1;
unsigned int prologue_end:1;
unsigned int epilogue_begin:1;
-
- Dwarf_Files *files;
};
struct Dwarf_Lines_s
@@ -414,11 +427,173 @@ extern int __libdw_visit_scopes (unsigned int depth,
void *arg)
__nonnull_attribute__ (2, 3) internal_function;
+/* Parse a DWARF Dwarf_Block into an array of Dwarf_Op's,
+ and cache the result (via tsearch). */
+extern int __libdw_intern_expression (Dwarf *dbg,
+ bool other_byte_order,
+ unsigned int address_size,
+ void **cache, const Dwarf_Block *block,
+ bool valuep,
+ Dwarf_Op **llbuf, size_t *listlen,
+ int sec_index)
+ __nonnull_attribute__ (4, 5, 7, 8) internal_function;
+
+
/* Return error code of last failing function call. This value is kept
separately for each thread. */
extern int __dwarf_errno_internal (void);
+/* Reader hooks. */
+
+/* Relocation hooks return -1 on error (in that case the error code
+ must already have been set), 0 if there is no relocation and 1 if a
+ relocation was present.*/
+
+static inline int
+__libdw_relocate_address (Dwarf *dbg __attribute__ ((unused)),
+ int sec_index __attribute__ ((unused)),
+ const void *addr __attribute__ ((unused)),
+ int width __attribute__ ((unused)),
+ Dwarf_Addr *val __attribute__ ((unused)))
+{
+ return 0;
+}
+
+static inline int
+__libdw_relocate_offset (Dwarf *dbg __attribute__ ((unused)),
+ int sec_index __attribute__ ((unused)),
+ const void *addr __attribute__ ((unused)),
+ int width __attribute__ ((unused)),
+ Dwarf_Off *val __attribute__ ((unused)))
+{
+ return 0;
+}
+
+static inline Elf_Data *
+__libdw_checked_get_data (Dwarf *dbg, int sec_index)
+{
+ Elf_Data *data = dbg->sectiondata[sec_index];
+ if (unlikely (data == NULL)
+ || unlikely (data->d_buf == NULL))
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return NULL;
+ }
+ return data;
+}
+
+static inline int
+__libdw_offset_in_section (Dwarf *dbg, int sec_index,
+ Dwarf_Off offset, size_t size)
+{
+ Elf_Data *data = __libdw_checked_get_data (dbg, sec_index);
+ if (data == NULL)
+ return -1;
+ if (unlikely (offset > data->d_size)
+ || unlikely (data->d_size - offset < size))
+ {
+ __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+ return -1;
+ }
+
+ return 0;
+}
+
+static inline bool
+__libdw_in_section (Dwarf *dbg, int sec_index,
+ const void *addr, size_t size)
+{
+ Elf_Data *data = __libdw_checked_get_data (dbg, sec_index);
+ if (data == NULL)
+ return false;
+ if (unlikely (addr < data->d_buf)
+ || unlikely (data->d_size - (addr - data->d_buf) < size))
+ {
+ __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+ return false;
+ }
+
+ return true;
+}
+
+#define READ_AND_RELOCATE(RELOC_HOOK, VAL) \
+ ({ \
+ if (!__libdw_in_section (dbg, sec_index, addr, width)) \
+ return -1; \
+ \
+ const unsigned char *orig_addr = addr; \
+ if (width == 4) \
+ VAL = read_4ubyte_unaligned_inc (dbg, addr); \
+ else \
+ VAL = read_8ubyte_unaligned_inc (dbg, addr); \
+ \
+ int status = RELOC_HOOK (dbg, sec_index, orig_addr, width, &VAL); \
+ if (status < 0) \
+ return status; \
+ status > 0; \
+ })
+
+static inline int
+__libdw_read_address_inc (Dwarf *dbg,
+ int sec_index, const unsigned char **addrp,
+ int width, Dwarf_Addr *ret)
+{
+ const unsigned char *addr = *addrp;
+ READ_AND_RELOCATE (__libdw_relocate_address, (*ret));
+ *addrp = addr;
+ return 0;
+}
+
+static inline int
+__libdw_read_address (Dwarf *dbg,
+ int sec_index, const unsigned char *addr,
+ int width, Dwarf_Addr *ret)
+{
+ READ_AND_RELOCATE (__libdw_relocate_address, (*ret));
+ return 0;
+}
+
+static inline int
+__libdw_read_offset_inc (Dwarf *dbg,
+ int sec_index, const unsigned char **addrp,
+ int width, Dwarf_Off *ret, int sec_ret,
+ size_t size)
+{
+ const unsigned char *addr = *addrp;
+ READ_AND_RELOCATE (__libdw_relocate_offset, (*ret));
+ *addrp = addr;
+ return __libdw_offset_in_section (dbg, sec_ret, *ret, size);
+}
+
+static inline int
+__libdw_read_offset (Dwarf *dbg,
+ int sec_index, const unsigned char *addr,
+ int width, Dwarf_Off *ret, int sec_ret,
+ size_t size)
+{
+ READ_AND_RELOCATE (__libdw_relocate_offset, (*ret));
+ return __libdw_offset_in_section (dbg, sec_ret, *ret, size);
+}
+
+/* Read up begin/end pair and increment read pointer.
+ - If it's normal range record, set up *BEGINP and *ENDP and return 0.
+ - If it's base address selection record, set up *BASEP and return 1.
+ - If it's end of rangelist, don't set anything and return 2
+ - If an error occurs, don't set anything and return <0. */
+int __libdw_read_begin_end_pair_inc (Dwarf *dbg, int sec_index,
+ unsigned char **addr, int width,
+ Dwarf_Addr *beginp, Dwarf_Addr *endp,
+ Dwarf_Addr *basep)
+ internal_function;
+
+unsigned char * __libdw_formptr (Dwarf_Attribute *attr, int sec_index,
+ int err_nodata, unsigned char **endpp,
+ Dwarf_Off *offsetp)
+ internal_function;
+
+
+
/* Aliases to avoid PLTs. */
INTDECL (dwarf_attr)
INTDECL (dwarf_attr_integrate)