diff options
| author | Roland McGrath <[email protected]> | 2005-10-28 06:56:24 +0000 |
|---|---|---|
| committer | Roland McGrath <[email protected]> | 2005-10-28 06:56:24 +0000 |
| commit | 07d4f2fc1cb53f170a71bc13617bbdd9cb1c3c60 (patch) | |
| tree | 0cd998a48772a7857dc187899cb5bb1f8decc35b /libdw | |
| parent | 89757447dbcd0ac946db345fa6aa1edc76a37a11 (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/ChangeLog | 60 | ||||
| -rw-r--r-- | libdw/Makefile.am | 11 | ||||
| -rw-r--r-- | libdw/dwarf.h | 2 | ||||
| -rw-r--r-- | libdw/dwarf_diecu.c | 46 | ||||
| -rw-r--r-- | libdw/dwarf_entry_breakpoints.c | 147 | ||||
| -rw-r--r-- | libdw/dwarf_entrypc.c | 35 | ||||
| -rw-r--r-- | libdw/dwarf_getsrc_die.c | 9 | ||||
| -rw-r--r-- | libdw/dwarf_getsrclines.c | 4 | ||||
| -rw-r--r-- | libdw/dwarf_haspc.c | 78 | ||||
| -rw-r--r-- | libdw/dwarf_ranges.c | 121 | ||||
| -rw-r--r-- | libdw/libdw.h | 26 | ||||
| -rw-r--r-- | libdw/libdw.map | 6 | ||||
| -rw-r--r-- | libdw/libdwP.h | 2 |
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) |
