summaryrefslogtreecommitdiffstats
path: root/libdw
diff options
context:
space:
mode:
authorRoland McGrath <[email protected]>2005-10-28 06:56:24 +0000
committerRoland McGrath <[email protected]>2005-10-28 06:56:24 +0000
commit07d4f2fc1cb53f170a71bc13617bbdd9cb1c3c60 (patch)
tree0cd998a48772a7857dc187899cb5bb1f8decc35b /libdw
parent89757447dbcd0ac946db345fa6aa1edc76a37a11 (diff)
libdw/
Fixes to last changes. tests/ 2005-10-27 Roland McGrath <[email protected]> * run-find-prologues.sh: New file. * Makefile.am (TESTS, EXTRA_DIST): Add it.
Diffstat (limited to 'libdw')
-rw-r--r--libdw/ChangeLog60
-rw-r--r--libdw/Makefile.am11
-rw-r--r--libdw/dwarf.h2
-rw-r--r--libdw/dwarf_diecu.c46
-rw-r--r--libdw/dwarf_entry_breakpoints.c147
-rw-r--r--libdw/dwarf_entrypc.c35
-rw-r--r--libdw/dwarf_getsrc_die.c9
-rw-r--r--libdw/dwarf_getsrclines.c4
-rw-r--r--libdw/dwarf_haspc.c78
-rw-r--r--libdw/dwarf_ranges.c121
-rw-r--r--libdw/libdw.h26
-rw-r--r--libdw/libdw.map6
-rw-r--r--libdw/libdwP.h2
13 files changed, 466 insertions, 81 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index db069c94..b74d26b0 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,63 @@
+2005-10-27 Roland McGrath <[email protected]>
+
+ * dwarf_entry_breakpoints.c (search_range): Fix binary search code;
+ don't match end_sequence markers.
+
+ * dwarf_getsrclines.c (compare_lines): Sort end_sequence markers
+ before normal records at the same address.
+ * dwarf_getsrc_die.c (dwarf_getsrc_die): Don't match an end_sequence
+ marker.
+
+2005-10-26 Roland McGrath <[email protected]>
+
+ * dwarf_entry_breakpoints.c: Use the second line record within the
+ function, regardless of its source location data.
+
+2005-10-25 Roland McGrath <[email protected]>
+
+ * dwarf_entry_breakpoints.c: Fall back to entrypc for contiguous too.
+
+ * libdw.map: Add dwarf_entrypc, dwarf_entry_breakpoints.
+
+2005-10-14 Roland McGrath <[email protected]>
+
+ * dwarf_diecu.c (dwarf_diecu): New file.
+ * Makefile.am (libdw_a_SOURCES): Add it.
+ * libdw.h: Declare dwarf_diecu.
+ * libdw.map: Export it.
+
+ * libdw.map: Bump to 0.116; export dwarf_ranges.
+
+2005-09-20 Roland McGrath <[email protected]>
+
+ * dwarf_haspc.c: Use dwarf_ranges.
+ * dwarf_entry_breakpoints.c: Likewise.
+
+ * dwarf_ranges.c: New file.
+ * Makefile.am (libdw_a_SOURCES): Add it.
+ * libdw.h: Declare dwarf_ranges.
+ * libdwP.h: Add INTDECL.
+
+2005-09-14 Roland McGrath <[email protected]>
+
+ * dwarf_entry_breakpoints.c (dwarf_entry_breakpoints): Fix braino in
+ prologue_end marker scanning loop.
+
+2005-09-11 Roland McGrath <[email protected]>
+
+ * dwarf.h: Comment typo fix.
+
+2005-09-07 Roland McGrath <[email protected]>
+
+ * dwarf_entry_breakpoints.c: New file.
+ * Makefile.am (libdw_a_SOURCES): Add it.
+ * libdw.h: Declare dwarf_entry_breakpoints.
+
+ * dwarf_entrypc.c: New file.
+ * Makefile.am (libdw_a_SOURCES): Add it.
+ * libdw.h: Declare dwarf_entrypc.
+ * libdwP.h: Add INTDECL.
+
2005-08-28 Ulrich Drepper <[email protected]>
* Makefile.am: Use $(LINK) not $(CC) when creating DSO.
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index a35f5dcc..12567139 100644
--- a/libdw/Makefile.am
+++ b/libdw/Makefile.am
@@ -42,10 +42,11 @@ libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
dwarf_attr_integrate.c dwarf_hasattr_integrate.c \
dwarf_child.c dwarf_haschildren.c dwarf_formaddr.c \
dwarf_formudata.c dwarf_formsdata.c dwarf_lowpc.c \
- dwarf_haspc.c dwarf_highpc.c \
+ dwarf_entrypc.c dwarf_haspc.c dwarf_highpc.c dwarf_ranges.c \
dwarf_formref.c dwarf_formref_die.c dwarf_siblingof.c \
- dwarf_dieoffset.c dwarf_cuoffset.c dwarf_hasattr.c \
- dwarf_hasform.c dwarf_whatform.c dwarf_whatattr.c \
+ dwarf_dieoffset.c dwarf_cuoffset.c dwarf_diecu.c \
+ dwarf_hasattr.c dwarf_hasform.c \
+ dwarf_whatform.c dwarf_whatattr.c \
dwarf_bytesize.c dwarf_arrayorder.c dwarf_bitsize.c \
dwarf_bitoffset.c dwarf_srclang.c dwarf_getabbrevtag.c \
dwarf_getabbrevcode.c dwarf_abbrevhaschildren.c \
@@ -68,8 +69,8 @@ libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
dwarf_func_line.c dwarf_func_col.c dwarf_func_die.c \
dwarf_func_inline.c dwarf_getsrc_file.c \
libdw_findcu.c libdw_form.c libdw_alloc.c memory-access.c \
- libdw_visit_scopes.c
-
+ libdw_visit_scopes.c \
+ dwarf_entry_breakpoints.c
if !MUDFLAP
libdw_pic_a_SOURCES =
diff --git a/libdw/dwarf.h b/libdw/dwarf.h
index 2268256f..bf53f51d 100644
--- a/libdw/dwarf.h
+++ b/libdw/dwarf.h
@@ -516,7 +516,7 @@ enum
};
-/* DWARF extended opcide encodings. */
+/* DWARF extended opcode encodings. */
enum
{
DW_LNE_end_sequence = 1,
diff --git a/libdw/dwarf_diecu.c b/libdw/dwarf_diecu.c
new file mode 100644
index 00000000..5b0f1b8c
--- /dev/null
+++ b/libdw/dwarf_diecu.c
@@ -0,0 +1,46 @@
+/* Return CU DIE containing given DIE.
+ Copyright (C) 2005 Red Hat, Inc.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include "libdwP.h"
+
+
+Dwarf_Die *
+dwarf_diecu (die, result, address_sizep, offset_sizep)
+ Dwarf_Die *die;
+ Dwarf_Die *result;
+ uint8_t *address_sizep;
+ uint8_t *offset_sizep;
+{
+ if (die == NULL)
+ return NULL;
+
+ /* Clear the entire DIE structure. This signals we have not yet
+ determined any of the information. */
+ memset (result, '\0', sizeof (Dwarf_Die));
+
+ result->addr = ((char *) die->cu->dbg->sectiondata[IDX_debug_info]->d_buf
+ + die->cu->start + 3 * die->cu->offset_size - 4 + 3);
+ result->cu = die->cu;
+
+ if (address_sizep != NULL)
+ *address_sizep = die->cu->address_size;
+ if (offset_sizep != NULL)
+ *offset_sizep = die->cu->offset_size;
+
+ return result;
+}
diff --git a/libdw/dwarf_entry_breakpoints.c b/libdw/dwarf_entry_breakpoints.c
new file mode 100644
index 00000000..30f03fd6
--- /dev/null
+++ b/libdw/dwarf_entry_breakpoints.c
@@ -0,0 +1,147 @@
+/* Find entry breakpoint locations for a function.
+ Copyright (C) 2005 Red Hat, Inc.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include "libdwP.h"
+#include <dwarf.h>
+#include <stdlib.h>
+
+
+int
+dwarf_entry_breakpoints (die, bkpts)
+ Dwarf_Die *die;
+ Dwarf_Addr **bkpts;
+{
+ int nbkpts = 0;
+ *bkpts = NULL;
+
+ /* Add one breakpoint location to the result vector. */
+ inline int add_bkpt (Dwarf_Addr pc)
+ {
+ Dwarf_Addr *newlist = realloc (*bkpts, ++nbkpts * sizeof newlist[0]);
+ if (newlist == NULL)
+ {
+ free (*bkpts);
+ *bkpts = NULL;
+ __libdw_seterrno (DWARF_E_NOMEM);
+ return -1;
+ }
+ newlist[nbkpts - 1] = pc;
+ *bkpts = newlist;
+ return nbkpts;
+ }
+
+ /* Fallback result, break at the entrypc/lowpc value. */
+ inline int entrypc_bkpt (void)
+ {
+ Dwarf_Addr pc;
+ return INTUSE(dwarf_entrypc) (die, &pc) < 0 ? -1 : add_bkpt (pc);
+ }
+
+ /* Fetch the CU's line records to look for this DIE's addresses. */
+ Dwarf_Die cudie =
+ {
+ .cu = die->cu,
+ .addr = ((char *) die->cu->dbg->sectiondata[IDX_debug_info]->d_buf
+ + die->cu->start + 3 * die->cu->offset_size - 4 + 3),
+ };
+ Dwarf_Lines *lines;
+ size_t nlines;
+ if (INTUSE(dwarf_getsrclines) (&cudie, &lines, &nlines) < 0)
+ {
+ int error = INTUSE (dwarf_errno) ();
+ if (error == DWARF_E_NO_DEBUG_LINE)
+ return entrypc_bkpt ();
+ __libdw_seterrno (error);
+ return -1;
+ }
+
+ /* Search a contiguous PC range for prologue-end markers.
+ If DWARF, look for proper markers.
+ Failing that, if ADHOC, look for the ad hoc convention. */
+ inline int search_range (Dwarf_Addr low, Dwarf_Addr high,
+ bool dwarf, bool adhoc)
+ {
+ size_t l = 0, u = nlines;
+ while (l < u)
+ {
+ size_t idx = (l + u) / 2;
+ if (lines->info[idx].addr < low)
+ l = idx + 1;
+ else if (lines->info[idx].addr > low)
+ u = idx;
+ else if (lines->info[idx].end_sequence)
+ l = idx + 1;
+ else
+ {
+ l = idx;
+ break;
+ }
+ }
+ if (l < u)
+ {
+ if (dwarf)
+ for (size_t i = l; i < u && lines->info[i].addr < high; ++i)
+ if (lines->info[i].prologue_end
+ && add_bkpt (lines->info[i].addr) < 0)
+ return -1;
+ if (adhoc && nbkpts == 0)
+ while (++l < nlines && lines->info[l].addr < high)
+ if (!lines->info[l].end_sequence)
+ return add_bkpt (lines->info[l].addr);
+ return nbkpts;
+ }
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+ }
+
+ /* Search each contiguous address range for DWARF prologue_end markers. */
+
+ Dwarf_Addr base;
+ Dwarf_Addr begin;
+ Dwarf_Addr end;
+ ptrdiff_t offset = INTUSE(dwarf_ranges) (die, 0, &base, &begin, &end);
+ if (offset < 0)
+ return -1;
+
+ /* Most often there is a single contiguous PC range for the DIE. */
+ if (offset == 1)
+ return search_range (begin, end, true, true) ?: entrypc_bkpt ();
+
+ Dwarf_Addr lowpc = (Dwarf_Addr) -1l;
+ Dwarf_Addr highpc = (Dwarf_Addr) -1l;
+ while (offset > 0)
+ {
+ /* We have an address range entry. */
+ if (search_range (begin, end, true, false) < 0)
+ return -1;
+
+ if (begin < lowpc)
+ {
+ lowpc = begin;
+ highpc = end;
+ }
+
+ offset = INTUSE(dwarf_ranges) (die, offset, &base, &begin, &end);
+ }
+
+ /* If we didn't find any proper DWARF markers, then look in the
+ lowest-addressed range for an ad hoc marker. Failing that,
+ fall back to just using the entrypc value. */
+ return (nbkpts
+ ?: (lowpc == (Dwarf_Addr) -1l ? 0
+ : search_range (lowpc, highpc, false, true))
+ ?: entrypc_bkpt ());
+}
diff --git a/libdw/dwarf_entrypc.c b/libdw/dwarf_entrypc.c
new file mode 100644
index 00000000..61a1d4be
--- /dev/null
+++ b/libdw/dwarf_entrypc.c
@@ -0,0 +1,35 @@
+/* Return entry PC attribute of DIE.
+ Copyright (C) 2003, 2005 Red Hat, Inc.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_entrypc (die, return_addr)
+ Dwarf_Die *die;
+ Dwarf_Addr *return_addr;
+{
+ Dwarf_Attribute attr_mem;
+
+ return INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (die, DW_AT_entry_pc,
+ &attr_mem)
+ ?: INTUSE(dwarf_attr) (die, DW_AT_low_pc,
+ &attr_mem),
+ return_addr);
+}
+INTDEF(dwarf_entrypc)
diff --git a/libdw/dwarf_getsrc_die.c b/libdw/dwarf_getsrc_die.c
index e3ce4f2a..753d48f7 100644
--- a/libdw/dwarf_getsrc_die.c
+++ b/libdw/dwarf_getsrc_die.c
@@ -36,7 +36,7 @@ dwarf_getsrc_die (Dwarf_Die *cudie, Dwarf_Addr addr)
size_t idx = (l + u) / 2;
if (addr < lines->info[idx].addr)
u = idx;
- else if (addr > lines->info[idx].addr)
+ else if (addr > lines->info[idx].addr || lines->info[idx].end_sequence)
l = idx + 1;
else
return &lines->info[idx];
@@ -51,7 +51,12 @@ dwarf_getsrc_die (Dwarf_Die *cudie, Dwarf_Addr addr)
information is faulty and no end-sequence marker is present, we
still ignore it. */
if (u > 0 && u < nlines && addr > lines->info[u - 1].addr)
- return &lines->info[u - 1];
+ {
+ while (lines->info[u - 1].end_sequence && u > 0)
+ --u;
+ if (u > 0)
+ return &lines->info[u - 1];
+ }
__libdw_seterrno (DWARF_E_ADDR_OUTOFRANGE);
return NULL;
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index 85fe35eb..a207b16a 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -43,6 +43,10 @@ compare_lines (const void *a, const void *b)
Dwarf_Line *const *p1 = a;
Dwarf_Line *const *p2 = b;
+ if ((*p1)->addr == (*p2)->addr)
+ /* An end_sequence marker precedes a normal record at the same address. */
+ return (*p2)->end_sequence - (*p1)->end_sequence;
+
return (*p1)->addr - (*p2)->addr;
}
diff --git a/libdw/dwarf_haspc.c b/libdw/dwarf_haspc.c
index 7f29296d..d2e737a5 100644
--- a/libdw/dwarf_haspc.c
+++ b/libdw/dwarf_haspc.c
@@ -25,81 +25,15 @@ dwarf_haspc (Dwarf_Die *die, Dwarf_Addr pc)
if (die == NULL)
return -1;
- /* Usually there is a single contiguous range. */
- Dwarf_Addr lowpc, highpc;
- if (INTUSE(dwarf_highpc) (die, &highpc) == 0
- && INTUSE(dwarf_lowpc) (die, &lowpc) == 0)
- return pc >= lowpc && pc < highpc;
-
- /* We have to look for a noncontiguous range. */
- Dwarf_Attribute attr_mem;
- Dwarf_Attribute *attr = INTUSE(dwarf_attr) (die, DW_AT_ranges, &attr_mem);
- if (attr == NULL)
- return -1;
-
- /* Must have the form data4 or data8 which act as an offset. */
- Dwarf_Word offset;
- if (INTUSE(dwarf_formudata) (attr, &offset) != 0)
- return -1;
-
- const Elf_Data *d = attr->cu->dbg->sectiondata[IDX_debug_ranges];
- if (d == NULL)
- {
- __libdw_seterrno (DWARF_E_NO_DEBUG_RANGES);
- return -1;
- }
-
- /* Fetch the CU's base address. */
Dwarf_Addr base;
- Dwarf_Die cudie =
- {
- .cu = attr->cu,
- .addr = ((char *) attr->cu->dbg->sectiondata[IDX_debug_info]->d_buf
- + attr->cu->start + 3 * attr->cu->offset_size - 4 + 3),
- };
- if (INTUSE(dwarf_lowpc) (&cudie, &base) != 0)
- return -1;
-
- unsigned char *readp = d->d_buf + offset;
Dwarf_Addr begin;
Dwarf_Addr end;
- do
- {
- next:
- if ((unsigned char *) d->d_buf + d->d_size - readp
- < attr->cu->address_size * 2)
- {
- __libdw_seterrno (DWARF_E_INVALID_DWARF);
- return -1;
- }
-
- if (attr->cu->address_size == 8)
- {
- begin = read_8ubyte_unaligned_inc (attr->cu->dbg, readp);
- end = read_8ubyte_unaligned_inc (attr->cu->dbg, readp);
- }
- else
- {
- begin = (Dwarf_Sword) read_4sbyte_unaligned_inc (attr->cu->dbg,
- readp);
- end = read_4ubyte_unaligned_inc (attr->cu->dbg, readp);
- }
-
- if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
- {
- base = end;
- goto next;
- }
-
- if (begin == 0 && end == 0) /* End of list entry. */
- /* This is not the droid you are looking for. */
- return 0;
-
- /* We have an address range entry. */
- }
- while (pc < base + begin || pc >= base + end);
+ ptrdiff_t offset = 0;
+ while ((offset = INTUSE(dwarf_ranges) (die, offset, &base,
+ &begin, &end)) > 0)
+ if (pc >= begin && pc < end)
+ return 1;
- /* This one matches the address. */
- return 1;
+ return offset;
}
INTDEF (dwarf_haspc)
diff --git a/libdw/dwarf_ranges.c b/libdw/dwarf_ranges.c
new file mode 100644
index 00000000..546bcac0
--- /dev/null
+++ b/libdw/dwarf_ranges.c
@@ -0,0 +1,121 @@
+/* Enumerate the PC ranges covered by a DIE.
+ Copyright (C) 2005 Red Hat, Inc.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <dwarf.h>
+#include <assert.h>
+
+
+ptrdiff_t
+dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
+ Dwarf_Addr *startp, Dwarf_Addr *endp)
+{
+ if (die == NULL)
+ return -1;
+
+ if (offset == 0
+ /* Usually there is a single contiguous range. */
+ && INTUSE(dwarf_highpc) (die, endp) == 0
+ && INTUSE(dwarf_lowpc) (die, startp) == 0)
+ /* A offset into .debug_ranges will never be 1, it must be at least a
+ multiple of 4. So we can return 1 as a special case value to mark
+ there are no ranges to look for on the next call. */
+ return 1;
+
+ if (offset == 1)
+ return 0;
+
+ /* We have to look for a noncontiguous range. */
+
+ const Elf_Data *d = die->cu->dbg->sectiondata[IDX_debug_ranges];
+ if (d == NULL)
+ {
+ __libdw_seterrno (DWARF_E_NO_DEBUG_RANGES);
+ return -1;
+ }
+
+ if (offset == 0)
+ {
+ Dwarf_Attribute attr_mem;
+ Dwarf_Attribute *attr = INTUSE(dwarf_attr) (die, DW_AT_ranges,
+ &attr_mem);
+ if (attr == NULL)
+ return -1;
+
+ /* Must have the form data4 or data8 which act as an offset. */
+ Dwarf_Word start_offset;
+ if (INTUSE(dwarf_formudata) (attr, &start_offset) != 0)
+ return -1;
+
+ offset = start_offset;
+ assert ((Dwarf_Word) offset == start_offset);
+
+ /* Fetch the CU's base address. */
+ Dwarf_Die cudie =
+ {
+ .cu = attr->cu,
+ .addr = ((char *) attr->cu->dbg->sectiondata[IDX_debug_info]->d_buf
+ + attr->cu->start + 3 * attr->cu->offset_size - 4 + 3),
+ };
+ if (INTUSE(dwarf_lowpc) (&cudie, basep) != 0)
+ return -1;
+ }
+ else if (offset < 0 || (size_t) offset >= d->d_size)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+ return -1l;
+ }
+
+ unsigned char *readp = d->d_buf + offset;
+
+ next:
+ if ((unsigned char *) d->d_buf + d->d_size - readp
+ < die->cu->address_size * 2)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+ }
+
+ Dwarf_Addr begin;
+ Dwarf_Addr end;
+ if (die->cu->address_size == 8)
+ {
+ begin = read_8ubyte_unaligned_inc (die->cu->dbg, readp);
+ end = read_8ubyte_unaligned_inc (die->cu->dbg, readp);
+ }
+ else
+ {
+ begin = (Dwarf_Sword) read_4sbyte_unaligned_inc (die->cu->dbg,
+ readp);
+ end = read_4ubyte_unaligned_inc (die->cu->dbg, readp);
+ }
+
+ if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
+ {
+ *basep = end;
+ goto next;
+ }
+
+ if (begin == 0 && end == 0) /* End of list entry. */
+ return 0;
+
+ /* We have an address range entry. */
+ *startp = *basep + begin;
+ *endp = *basep + end;
+ return readp - (unsigned char *) d->d_buf;
+}
+INTDEF (dwarf_ranges)
diff --git a/libdw/libdw.h b/libdw/libdw.h
index 350aa440..2bce26bd 100644
--- a/libdw/libdw.h
+++ b/libdw/libdw.h
@@ -194,6 +194,10 @@ extern Dwarf_Off dwarf_dieoffset (Dwarf_Die *die);
/* Return offset of DIE in CU. */
extern Dwarf_Off dwarf_cuoffset (Dwarf_Die *die);
+/* Return CU DIE containing given DIE. */
+extern Dwarf_Die *dwarf_diecu (Dwarf_Die *die, Dwarf_Die *result,
+ uint8_t *address_sizep, uint8_t *offset_sizep);
+
/* Return CU DIE containing given address. */
extern Dwarf_Die *dwarf_addrdie (Dwarf *dbg, Dwarf_Addr addr,
Dwarf_Die *result) __nonnull_attribute__ (3);
@@ -292,10 +296,26 @@ extern int dwarf_highpc (Dwarf_Die *die, Dwarf_Addr *return_addr)
extern int dwarf_lowpc (Dwarf_Die *die, Dwarf_Addr *return_addr)
__nonnull_attribute__ (2);
+/* Return entry_pc or low_pc attribute of DIE. */
+extern int dwarf_entrypc (Dwarf_Die *die, Dwarf_Addr *return_addr)
+ __nonnull_attribute__ (2);
+
/* Return 1 if DIE's lowpc/highpc or ranges attributes match the PC address,
0 if not, or -1 for errors. */
extern int dwarf_haspc (Dwarf_Die *die, Dwarf_Addr pc);
+/* Enumerate the PC address ranges covered by this DIE, covering all
+ addresses where dwarf_haspc returns true. In the first call OFFSET
+ should be zero and *BASEP need not be initialized. Returns -1 for
+ errors, zero when there are no more address ranges to report, or a
+ nonzero OFFSET value to pass to the next call. Each subsequent call
+ must preserve *BASEP from the prior call. Successful calls fill in
+ *STARTP and *ENDP with a contiguous address range. */
+extern ptrdiff_t dwarf_ranges (Dwarf_Die *die,
+ ptrdiff_t offset, Dwarf_Addr *basep,
+ Dwarf_Addr *startp, Dwarf_Addr *endp);
+
+
/* Return byte size attribute of DIE. */
extern int dwarf_bytesize (Dwarf_Die *die);
@@ -530,6 +550,12 @@ extern int dwarf_func_inline_instances (Dwarf_Func *func,
void *arg);
+/* Find the appropriate PC location or locations for function entry
+ breakpoints for the given DW_TAG_subprogram DIE. Returns -1 for errors.
+ On success, returns the number of breakpoint locations (never zero)
+ and sets *BKPTS to a malloc'd vector of addresses. */
+extern int dwarf_entry_breakpoints (Dwarf_Die *die, Dwarf_Addr **bkpts);
+
/* Call callback function for each of the macro information entry for
the CU. */
diff --git a/libdw/libdw.map b/libdw/libdw.map
index a5324bd1..3849b320 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -1,5 +1,5 @@
ELFUTILS_0 { };
-ELFUTILS_0.115 {
+ELFUTILS_0.116 {
global:
dwarf_abbrevhaschildren;
dwarf_addrdie;
@@ -16,9 +16,12 @@ ELFUTILS_0.115 {
dwarf_cuoffset;
dwarf_diename;
dwarf_dieoffset;
+ dwarf_diecu;
dwarf_end;
dwarf_errmsg;
dwarf_errno;
+ dwarf_entrypc;
+ dwarf_entry_breakpoints;
dwarf_filesrc;
dwarf_formaddr;
dwarf_formblock;
@@ -86,6 +89,7 @@ ELFUTILS_0.115 {
dwarf_onesrcline;
dwarf_nextcu;
dwarf_new_oom_handler;
+ dwarf_ranges;
dwarf_siblingof;
dwarf_srclang;
dwarf_tag;
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 37f28721..4dbe77e3 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -373,6 +373,7 @@ INTDECL (dwarf_child)
INTDECL (dwarf_dieoffset)
INTDECL (dwarf_diename)
INTDECL (dwarf_end)
+INTDECL (dwarf_entrypc)
INTDECL (dwarf_errmsg)
INTDECL (dwarf_formaddr)
INTDECL (dwarf_formblock)
@@ -393,6 +394,7 @@ INTDECL (dwarf_highpc)
INTDECL (dwarf_lowpc)
INTDECL (dwarf_nextcu)
INTDECL (dwarf_offdie)
+INTDECL (dwarf_ranges)
INTDECL (dwarf_siblingof)
INTDECL (dwarf_tag)