[PATCH] Note that .rela.debug* sections are debuginfo sections.
by Nick Alcock
Without this fix, strip -g misbehaves when stripping object files
and other ELF objects containing debuginfo relocation sections,
preserving all debuginfo sections in the output file because the
.rela.debug* sections reference them.
Signed-off-by: Nick Alcock <nick.alcock(a)oracle.com>
---
The selection of sections to RELAFY here is pretty much arbitrary,
covering everything I've seen .rela.* created for and anything else that
seems likely to need it.
Testing is trivial: try to strip -g a Linux kernel module (or any other
object file containing debug info) and observe the .debug* and
.rela.debug* sections turning up in the stripped output rather than (if
specified) the -f file. binutils behaves correctly in this area.
I haven't considered DWARF 1 sections not shared with DWARF 2+ at all
because I have no way to generate such sections for testing.
libebl/ChangeLog | 5 +++++
libebl/eblopenbackend.c | 36 +++++++++++++++++++-----------------
2 files changed, 24 insertions(+), 17 deletions(-)
diff --git a/libebl/ChangeLog b/libebl/ChangeLog
index af819a2..c6204c6 100644
--- a/libebl/ChangeLog
+++ b/libebl/ChangeLog
@@ -1,3 +1,8 @@
+2012-09-18 Nick Alcock <nick.alcock(a)oracle.com>
+
+ * eblopenbackend.c (default_debugscn_p): Add .rela.* versions of
+ many DWARF 2+ debuginfo sections.
+
2012-08-22 Jeff Kenton <jkenton(a)tilera.com>
* eblopenbackend.c (machines): Add tilegx.
diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c
index 89e5da5..d10b0d0 100644
--- a/libebl/eblopenbackend.c
+++ b/libebl/eblopenbackend.c
@@ -619,6 +619,7 @@ default_object_note (const char *name __attribute__ ((unused)),
static bool
default_debugscn_p (const char *name)
{
+#define RELAFY(x) x, ".rela" x
/* We know by default only about the DWARF debug sections which have
fixed names. */
static const char *dwarf_scn_names[] =
@@ -630,31 +631,32 @@ default_debugscn_p (const char *name)
".debug_srcinfo",
".debug_sfnames",
/* DWARF 1.1 and DWARF 2 */
- ".debug_aranges",
- ".debug_pubnames",
+ RELAFY(".debug_aranges"),
+ RELAFY(".debug_pubnames"),
/* DWARF 2 */
- ".debug_info",
- ".debug_abbrev",
- ".debug_line",
- ".debug_frame",
- ".debug_str",
- ".debug_loc",
- ".debug_macinfo",
+ RELAFY(".debug_info"),
+ RELAFY(".debug_abbrev"),
+ RELAFY(".debug_line"),
+ RELAFY(".debug_frame"),
+ RELAFY(".debug_str"),
+ RELAFY(".debug_loc"),
+ RELAFY(".debug_macinfo"),
/* DWARF 3 */
- ".debug_ranges",
- ".debug_pubtypes",
+ RELAFY(".debug_ranges"),
+ RELAFY(".debug_pubtypes"),
/* DWARF 4 */
- ".debug_types",
+ RELAFY(".debug_types"),
/* GDB DWARF 4 extension */
".gdb_index",
/* GNU/DWARF 5 extension/proposal */
- ".debug_macro",
+ RELAFY(".debug_macro"),
/* SGI/MIPS DWARF 2 extensions */
- ".debug_weaknames",
- ".debug_funcnames",
- ".debug_typenames",
- ".debug_varnames"
+ RELAFY(".debug_weaknames"),
+ RELAFY(".debug_funcnames"),
+ RELAFY(".debug_typenames"),
+ RELAFY(".debug_varnames")
};
+#undef RELAFY
const size_t ndwarf_scn_names = (sizeof (dwarf_scn_names)
/ sizeof (dwarf_scn_names[0]));
for (size_t cnt = 0; cnt < ndwarf_scn_names; ++cnt)
--
1.7.12.156.gd7c4257
--
NULL && (void)
10 years, 7 months
[COMMITTED] Make sure --enable-dwz code is also tested during make distcheck.
by Mark Wielaard
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
ChangeLog | 4 ++++
Makefile.am | 2 +-
2 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 102b43b..0ddc070 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-09-20 Mark Wielaard <mjw(a)redhat.com>
+
+ * Makefile.am (DISTCHECK_CONFIGURE_FLAGS): Add --enable-dwz.
+
2013-07-25 Jan Kratochvil <jan.kratochvil(a)redhat.com>
* configure.ac: Set version to 0.156.
diff --git a/Makefile.am b/Makefile.am
index e833989..7db05f8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -35,7 +35,7 @@ EXTRA_DIST = elfutils.spec GPG-KEY NOTES CONTRIBUTING \
# Run all tests under valgrind.
DISTCHECK_CONFIGURE_FLAGS = \
--libdir=`echo $(libdir) | sed "s,^$(exec_prefix),$$dc_install_base,"`\
- --enable-valgrind \
+ --enable-valgrind --enable-dwz \
CC="$(CC)"
distcheck-hook:
--
1.7.1
10 years, 7 months
[PATCH] ignore a few more files
by Mike Frysinger
Signed-off-by: Mike Frysinger <vapier(a)gentoo.org>
---
.gitignore | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/.gitignore b/.gitignore
index d463556..4ab7b24 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@
*.pot
*.rej
*.so
+*.so.[0-9]
*/Makefile.in
*~
.#*
@@ -36,6 +37,30 @@ configure
elfutils.spec
libcpu/*_dis.h
libdw/known-dwarf.h
+po/POTFILES
po/en(a)boldquot.po
+po/en(a)boldquot.insert-header
po/en(a)quot.po
+po/en(a)quot.insert-header
+po/stamp-po
+po/remove-potcdate.sed
+src/addr2line
+src/ar
+src/elfcmp
+src/elflint
+src/findtextrel
+src/ld
+src/ldlex.c
+src/ldscript.c
+src/ldscript.h
+src/make-debug-archive
+src/nm
+src/objdump
+src/ranlib
+src/readelf
+src/size
+src/strings
+src/strip
+src/unstrip
stamp-h1
+/version.h
--
1.8.3.2
10 years, 7 months
[PATCH] libdwfl: Fix memory leak in cu.c on bad DWARF.
by Mark Wielaard
If libdw dwarf_offdie fails free cu structure.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdwfl/ChangeLog | 4 ++++
libdwfl/cu.c | 5 ++++-
2 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index d325475..4d119fd 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,5 +1,9 @@
2013-09-12 Mark Wielaard <mjw(a)redhat.com>
+ * cu.c (intern_cu): If dwarf_offdie fails free cu.
+
+2013-09-12 Mark Wielaard <mjw(a)redhat.com>
+
* linux-proc-maps.c (proc_maps_report): Don't fclose FILE in
bad_report.
diff --git a/libdwfl/cu.c b/libdwfl/cu.c
index 18fc206..40b0201 100644
--- a/libdwfl/cu.c
+++ b/libdwfl/cu.c
@@ -204,7 +204,10 @@ intern_cu (Dwfl_Module *mod, Dwarf_Off cuoff, struct dwfl_cu **result)
/* XXX use non-searching lookup */
Dwarf_Die *die = INTUSE(dwarf_offdie) (mod->dw, cuoff, &cu->die);
if (die == NULL)
- return DWFL_E_LIBDW;
+ {
+ free (cu);
+ return DWFL_E_LIBDW;
+ }
assert (die == &cu->die);
struct dwfl_cu **newvec = realloc (mod->cu, ((mod->ncu + 1)
--
1.7.1
10 years, 7 months
[PATCH] Fix memory leak and set libdw errno when intern_fde cannot parse start/end.
by Mark Wielaard
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdw/ChangeLog | 5 +++++
libdw/fde.c | 6 +++++-
2 files changed, 10 insertions(+), 1 deletions(-)
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index c8398b2..1a85194 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2013-09-12 Mark Wielaard <mjw(a)redhat.com>
+
+ * fde.c (intern_fde): Free fde and set libdw errno when start
+ or end could not be read.
+
2013-08-24 Mark Wielaard <mjw(a)redhat.com>
* dwarf_getlocation.c (store_implicit_value): Don't take data
diff --git a/libdw/fde.c b/libdw/fde.c
index 32c77b0..91ce732 100644
--- a/libdw/fde.c
+++ b/libdw/fde.c
@@ -83,7 +83,11 @@ intern_fde (Dwarf_CFI *cache, const Dwarf_FDE *entry)
&fde->instructions, &fde->start))
|| unlikely (read_encoded_value (cache, cie->fde_encoding & 0x0f,
&fde->instructions, &fde->end)))
- return NULL;
+ {
+ free (fde);
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return NULL;
+ }
fde->end += fde->start;
fde->cie = cie;
--
1.7.1
10 years, 7 months
[PATCH] libdwfl: proc_maps_report should not fclose the given file.
by Mark Wielaard
Calling fclose only on bad_report, but not on other errors or success
is confusing. The caller is always responsible for calling fclose on
the given file. Otherwise flcose might be called twice (e.g. in
dwfl_linux_proc_report).
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdwfl/ChangeLog | 5 +++++
libdwfl/linux-proc-maps.c | 1 -
2 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index df7a50f..d325475 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,5 +1,10 @@
2013-09-12 Mark Wielaard <mjw(a)redhat.com>
+ * linux-proc-maps.c (proc_maps_report): Don't fclose FILE in
+ bad_report.
+
+2013-09-12 Mark Wielaard <mjw(a)redhat.com>
+
* dwfl_module_getdwarf.c (find_symtab): Call elf_getdata with
aux_xndxscn, not xndxscn, for aux_symxndxdata.
diff --git a/libdwfl/linux-proc-maps.c b/libdwfl/linux-proc-maps.c
index 67ff509..10946b9 100644
--- a/libdwfl/linux-proc-maps.c
+++ b/libdwfl/linux-proc-maps.c
@@ -221,7 +221,6 @@ proc_maps_report (Dwfl *dwfl, FILE *f, GElf_Addr sysinfo_ehdr, pid_t pid)
{
bad_report:
free (line);
- fclose (f);
return -1;
}
--
1.7.1
10 years, 7 months
[COMMITTED] Fix typo in dwfl_module_getdwarf.c (find_symtab).
by Mark Wielaard
Call elf_getdata with aux_xndxscn, not xndxscn, for aux_symxndxdata.
This was a copy/paste error from the code just above for symxndxdata.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdwfl/ChangeLog | 5 +++++
libdwfl/dwfl_module_getdwarf.c | 2 +-
2 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 90ba686..df7a50f 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,8 @@
+2013-09-12 Mark Wielaard <mjw(a)redhat.com>
+
+ * dwfl_module_getdwarf.c (find_symtab): Call elf_getdata with
+ aux_xndxscn, not xndxscn, for aux_symxndxdata.
+
2013-08-25 Mark Wielaard <mjw(a)redhat.com>
* linux-kernel-modules.c (report_kernel): Pass add_p_vaddr as true
diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c
index d35c266..7a65ec3 100644
--- a/libdwfl/dwfl_module_getdwarf.c
+++ b/libdwfl/dwfl_module_getdwarf.c
@@ -1077,7 +1077,7 @@ find_symtab (Dwfl_Module *mod)
mod->aux_symxndxdata = NULL;
else
{
- mod->aux_symxndxdata = elf_getdata (xndxscn, NULL);
+ mod->aux_symxndxdata = elf_getdata (aux_xndxscn, NULL);
if (mod->aux_symxndxdata == NULL)
goto aux_cleanup;
}
--
1.7.1
10 years, 7 months
[PATCH] libdw: Add new function dwarf_getlocations.
by Mark Wielaard
Using dwarf_getlocation it is possible to get single location
descriptions and with dwarf_getlocation_addr it is possible to
get a location list covering a specific address. But sometimes
it is more convenient to get all ranges covered by a location
list. For example when a specific address isn't covered and
you want to find alternative addresses where a location
description is defined.
dwarf_getlocations is modelled after dwarf_ranges. It enumerates
the location ranges and descriptions covered by the given
attribute. In the first call OFFSET should be zero and *BASEP
need not be initialized. Returns -1 for errors, zero when
there are no more locations 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 and *EXPR with
a pointer to an array of operations with length *EXPRLEN. If
the attribute describes a single location description and not a
location list the first call (with OFFSET zero) will return the
location description in *EXPR with *STARTP set to zero and *ENDP
set to minus one.
ptrdiff_t dwarf_getlocations (Dwarf_Attribute *attr, ptrdiff_t offset,
Dwarf_Addr *basep, Dwarf_Addr *startp,
Dwarf_Addr *endp, Dwarf_Op **expr,
size_t *exprlen);
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdw/ChangeLog | 9 ++
libdw/dwarf_getlocation.c | 182 ++++++++++++++++++++++++++++++++++++++-------
libdw/libdw.h | 18 ++++-
libdw/libdw.map | 5 +
4 files changed, 186 insertions(+), 28 deletions(-)
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index aa1e2cc..18ddd9e 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,12 @@
+2013-08-23 Mark Wielaard <mjw(a)redhat.com>
+
+ * dwarf_getlocation.c (attr_ok): Also accept DW_AT_segment.
+ (attr_base_address): New function, taken from...
+ (dwarf_getlocation_addr): here. Use attr_base_address.
+ (dwarf_getlocations): New function.
+ * libdw.h (dwarf_getlocations): New function definition.
+ * libdw.map (ELFUTILS_0.157): New.
+
2013-07-02 Mark Wielaard <mjw(a)redhat.com>
* dwarf_getsrclines.c (dwarf_getsrclines): Add new stack allocation
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c
index c3f3f47..2af0df7 100644
--- a/libdw/dwarf_getlocation.c
+++ b/libdw/dwarf_getlocation.c
@@ -1,5 +1,5 @@
/* Return location expression list.
- Copyright (C) 2000-2010 Red Hat, Inc.
+ Copyright (C) 2000-2010, 2013 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper(a)redhat.com>, 2000.
@@ -56,6 +56,7 @@ attr_ok (Dwarf_Attribute *attr)
case DW_AT_frame_base:
case DW_AT_return_addr:
case DW_AT_static_link:
+ case DW_AT_segment:
break;
default:
@@ -567,6 +568,37 @@ dwarf_getlocation (attr, llbuf, listlen)
return getlocation (attr->cu, &block, llbuf, listlen, cu_sec_idx (attr->cu));
}
+static int
+attr_base_address (attr, basep)
+ Dwarf_Attribute *attr;
+ Dwarf_Addr *basep;
+{
+ /* Fetch the CU's base address. */
+ Dwarf_Die cudie = CUDIE (attr->cu);
+
+ /* Find the base address of the compilation unit. It will
+ normally be specified by DW_AT_low_pc. In DWARF-3 draft 4,
+ the base address could be overridden by DW_AT_entry_pc. It's
+ been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc
+ for compilation units with discontinuous ranges. */
+ Dwarf_Attribute attr_mem;
+ if (unlikely (INTUSE(dwarf_lowpc) (&cudie, basep) != 0)
+ && INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (&cudie,
+ DW_AT_entry_pc,
+ &attr_mem),
+ basep) != 0)
+ {
+ if (INTUSE(dwarf_errno) () != 0)
+ return -1;
+
+ /* The compiler provided no base address when it should
+ have. Buggy GCC does this when it used absolute
+ addresses in the location list and no DW_AT_ranges. */
+ *basep = 0;
+ }
+ return 0;
+}
+
int
dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs)
Dwarf_Attribute *attr;
@@ -646,32 +678,8 @@ dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs)
goto invalid;
readp += block.length;
- if (base == (Dwarf_Addr) -1)
- {
- /* Fetch the CU's base address. */
- Dwarf_Die cudie = CUDIE (attr->cu);
-
- /* Find the base address of the compilation unit. It will
- normally be specified by DW_AT_low_pc. In DWARF-3 draft 4,
- the base address could be overridden by DW_AT_entry_pc. It's
- been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc
- for compilation units with discontinuous ranges. */
- Dwarf_Attribute attr_mem;
- if (unlikely (INTUSE(dwarf_lowpc) (&cudie, &base) != 0)
- && INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (&cudie,
- DW_AT_entry_pc,
- &attr_mem),
- &base) != 0)
- {
- if (INTUSE(dwarf_errno) () != 0)
- return -1;
-
- /* The compiler provided no base address when it should
- have. Buggy GCC does this when it used absolute
- addresses in the location list and no DW_AT_ranges. */
- base = 0;
- }
- }
+ if (base == (Dwarf_Addr) -1 && attr_base_address (attr, &base) != 0)
+ return -1;
if (address >= base + begin && address < base + end)
{
@@ -687,3 +695,123 @@ dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs)
return got;
}
+
+ptrdiff_t
+dwarf_getlocations (attr, offset, basep, startp, endp, expr, exprlen)
+ Dwarf_Attribute *attr;
+ ptrdiff_t offset;
+ Dwarf_Addr *basep;
+ Dwarf_Addr *startp;
+ Dwarf_Addr *endp;
+ Dwarf_Op **expr;
+ size_t *exprlen;
+{
+ if (! attr_ok (attr))
+ return -1;
+
+ /* 1 is an invalid offset, meaning no more locations. */
+ if (offset == 1)
+ return 0;
+
+ if (offset == 0)
+ {
+ /* If it has a block form, it's a single location expression. */
+ Dwarf_Block block;
+ if (INTUSE(dwarf_formblock) (attr, &block) == 0)
+ {
+ if (getlocation (attr->cu, &block, expr, exprlen,
+ cu_sec_idx (attr->cu)) != 0)
+ return -1;
+
+ /* This is the one and only location covering everything. */
+ *startp = 0;
+ *endp = -1;
+ return 1;
+ }
+
+ int error = INTUSE(dwarf_errno) ();
+ if (unlikely (error != DWARF_E_NO_BLOCK))
+ {
+ __libdw_seterrno (error);
+ return -1;
+ }
+
+ int result = check_constant_offset (attr, expr, exprlen);
+ if (result != 1)
+ {
+ if (result == 0)
+ {
+ /* This is the one and only location covering everything. */
+ *startp = 0;
+ *endp = -1;
+ return 1;
+ }
+ return result;
+ }
+
+ /* We must be looking at a true loclistptr, fetch the initial
+ base address and offset. */
+ if (attr_base_address (attr, basep) != 0)
+ return -1;
+
+ Dwarf_Word start_offset;
+ if (__libdw_formptr (attr, IDX_debug_loc,
+ DWARF_E_NO_LOCLIST,
+ NULL, &start_offset) == NULL)
+ return -1;
+ offset = start_offset;
+ }
+
+ const Elf_Data *d = attr->cu->dbg->sectiondata[IDX_debug_loc];
+ if (d == NULL)
+ {
+ __libdw_seterrno (DWARF_E_NO_LOCLIST);
+ return -1;
+ }
+
+ unsigned char *readp = d->d_buf + offset;
+ unsigned char *readendp = d->d_buf + d->d_size;
+
+ next:
+ if (readendp - readp < attr->cu->address_size * 2)
+ {
+ invalid:
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+ }
+
+ Dwarf_Addr begin;
+ Dwarf_Addr end;
+
+ switch (__libdw_read_begin_end_pair_inc (attr->cu->dbg, IDX_debug_loc,
+ &readp, attr->cu->address_size,
+ &begin, &end, basep))
+ {
+ case 0: /* got location range. */
+ break;
+ case 1: /* base address setup. */
+ goto next;
+ case 2: /* end of loclist */
+ return 0;
+ default: /* error */
+ return -1;
+ }
+
+ if (readendp - readp < 2)
+ goto invalid;
+
+ /* We have a location expression. */
+ Dwarf_Block block;
+ block.length = read_2ubyte_unaligned_inc (attr->cu->dbg, readp);
+ block.data = readp;
+ if (readendp - readp < (ptrdiff_t) block.length)
+ goto invalid;
+ readp += block.length;
+
+ if (getlocation (attr->cu, &block, expr, exprlen, IDX_debug_loc) != 0)
+ return -1;
+
+ *startp = *basep + begin;
+ *endp = *basep + end;
+ return readp - (unsigned char *) d->d_buf;
+}
diff --git a/libdw/libdw.h b/libdw/libdw.h
index f5fc4e2..898aa74 100644
--- a/libdw/libdw.h
+++ b/libdw/libdw.h
@@ -1,5 +1,5 @@
/* Interfaces for libdw.
- Copyright (C) 2002-2010 Red Hat, Inc.
+ Copyright (C) 2002-2010, 2013 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -630,6 +630,22 @@ extern int dwarf_getlocation_addr (Dwarf_Attribute *attr, Dwarf_Addr address,
Dwarf_Op **exprs, size_t *exprlens,
size_t nlocs);
+/* Enumerate the locations ranges and descriptions covered by the
+ given attribute. In the first call OFFSET should be zero and
+ *BASEP need not be initialized. Returns -1 for errors, zero when
+ there are no more locations 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 and *EXPR with a pointer to
+ an array of operations with length *EXPRLEN. If the attribute
+ describes a single location description and not a location list the
+ first call (with OFFSET zero) will return the location description
+ in *EXPR with *STARTP set to zero and *ENDP set to minus one. */
+extern ptrdiff_t dwarf_getlocations (Dwarf_Attribute *attr,
+ ptrdiff_t offset, Dwarf_Addr *basep,
+ Dwarf_Addr *startp, Dwarf_Addr *endp,
+ Dwarf_Op **expr, size_t *exprlen);
+
/* Return the block associated with a DW_OP_implicit_value operation.
The OP pointer must point into an expression that dwarf_getlocation
or dwarf_getlocation_addr has returned given the same ATTR. */
diff --git a/libdw/libdw.map b/libdw/libdw.map
index d38a8ef..2d2d37c 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -260,3 +260,8 @@ ELFUTILS_0.156 {
# Replaced ELFUTILS_0.122 version, which has a wrapper without add_p_vaddr.
dwfl_report_elf;
} ELFUTILS_0.149;
+
+ELFUTILS_0.157 {
+ global:
+ dwarf_getlocations;
+} ELFUTILS_0.156;
--
1.7.1
10 years, 7 months
Fix abi_cfi run-addrcfi.sh testcase and repost patches
by Mark Wielaard
The original run-addrcfi.sh testcase for the abi_cfi hook contained
a small error and would not correctly display the difference between
same_value and undefined rules. Which made the test less useful than
intended. I updated and reviewed all the new expected outputs again
and this also incorporates the review comments from Roland for the
last patch in the series. Just reposting them all for people to
look at again. The only real difference (besides the review updates
and the addrcfi.c fixlet) is just the expected outputs.
[PATCH 1/5] tests: Add run-addrcfi.sh test for libdw cfi dwarf_frame_* functions.
[PATCH 2/5] backends: Hook abi_cfi for ppc and s390.
[PATCH 3/5] tests: Add ppc32 and ppc64 addrcfi testcases.
[PATCH 4/5] tests: Add s390 and s390x addrcfi testcases.
[PATCH 5/5] backends: Hook abi_cfi for arm.
10 years, 7 months
[PATCH] libdw: Add new functions dwarf_getlocation_attr and dwarf_getlocation_die.
by Mark Wielaard
Some location expression operations have a DIE associated with them.
Examples are some of the new GNU typed DWARF extensions, DW_OP_GNU_convert,
DW_OP_GNU_reinterpret, DW_OP_GNU_const_type, DW_OP_GNU_regval_type and
DW_OP_GNU_deref_type. Others have (block) values associated with them,
like DW_OP_GNU_entry_value and DW_OP_GNU_const_type.
It is not always easy to access these values. The DIE offset is given in
various formats either as global offset or CU relative offset. The (block)
value might be constant or a location description. And the block might be
encoded with a uleb128 or ubyte length. The new functions help to easily
get at the DIE or attribute value.
In theory dwarf_getlocation_attr could be used for all cases, since
besides returning DW_AT_const_value or DW_AT_location, it could also
return an attribute referencing a DIE. But at least one operation,
DW_OP_GNU_const_type, has both a (type) DIE and a constant (block)
value associated with it. And directly getting the DIE when needed
is easier than first having to retrieve a (synthesized) attribute
and then getting the actual (type) DIE.
Expression operations that reference an actual DIE for the
DW_AT_location or DW_AT_const_value, like DW_OP_call2, DW_OP_call4,
DW_OP_callref and DW_OP_GNU_implicit_pointer can be used with both
dwarf_getlocation_attr and dwarf_getlocation_die.
DW_OP_implicit_value and DW_OP_GNU_implicit_pointer already had
their own special accessors (dwarf_getlocation_implicit_value
and dwarf_getlocation_implicit_pointer), but it seemed consistent
to include them in the new more generic accessors too.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdw/ChangeLog | 19 ++++++++
libdw/Makefile.am | 3 +-
libdw/dwarf_getlocation.c | 37 ++++++++-------
libdw/dwarf_getlocation_attr.c | 103 +++++++++++++++++++++++++++++++++++++++++
libdw/dwarf_getlocation_die.c | 78 +++++++++++++++++++++++++++++++
libdw/libdw.h | 23 +++++++++
libdw/libdw.map | 2 +
libdw/libdwP.h | 3 +-
8 files changed, 250 insertions(+), 18 deletions(-)
create mode 100644 libdw/dwarf_getlocation_attr.c
create mode 100644 libdw/dwarf_getlocation_die.c
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 18ddd9e..78dcf69 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,22 @@
+2013-08-24 Mark Wielaard <mjw(a)redhat.com>
+
+ * dwarf_getlocation.c (store_implicit_value): Don't take data
+ as argument, get block data from op number2. Return false when
+ block data length and op number don't match up.
+ (__libdw_intern_expression): Store start of block for
+ DW_OP_implicit_value and DW_OP_GNU_entry_value instead of
+ relative data offset. Also store block start (including length)
+ for DW_OP_GNU_const_type. Don't pass data to store_implicit_value.
+ * dwarf_getlocation_attr.c: New file.
+ * dwarf_getlocation_die.c: Likewise.
+ * libdw.h (dwarf_getlocation_die): New function definition.
+ (dwarf_getlocation_attr): Likewise.
+ * libdwP.h: Declare internal dwarf_getlocation_die.
+ * libdw.map (ELFUTILS_0.157): Add dwarf_getlocation_die and
+ dwarf_getlocation_attr.
+ * Makefile.am (libdw_a_SOURCES): Add dwarf_getlocation_die.c and
+ dwarf_getlocation_attr.c.
+
2013-08-23 Mark Wielaard <mjw(a)redhat.com>
* dwarf_getlocation.c (attr_ok): Also accept DW_AT_segment.
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index 71a006f..5fef2e1 100644
--- a/libdw/Makefile.am
+++ b/libdw/Makefile.am
@@ -87,7 +87,8 @@ libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
dwarf_frame_info.c dwarf_frame_cfa.c dwarf_frame_register.c \
dwarf_cfi_addrframe.c \
dwarf_getcfi.c dwarf_getcfi_elf.c dwarf_cfi_end.c \
- dwarf_aggregate_size.c dwarf_getlocation_implicit_pointer.c
+ dwarf_aggregate_size.c dwarf_getlocation_implicit_pointer.c \
+ dwarf_getlocation_die.c dwarf_getlocation_attr.c
if MAINTAINER_MODE
BUILT_SOURCES = $(srcdir)/known-dwarf.h
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c
index 2af0df7..428299f 100644
--- a/libdw/dwarf_getlocation.c
+++ b/libdw/dwarf_getlocation.c
@@ -95,13 +95,15 @@ loc_compare (const void *p1, const void *p2)
/* For each DW_OP_implicit_value, we store a special entry in the cache.
This points us directly to the block data for later fetching. */
static void
-store_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op,
- unsigned char *data)
+store_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op)
{
struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s,
sizeof (struct loc_block_s), 1);
+ const unsigned char *data = (const unsigned char *) op->number2;
+ Dwarf_Word blength; // Ignored, equal to op->number.
+ get_uleb128 (blength, data);
block->addr = op;
- block->data = data + op->number2;
+ block->data = (unsigned char *) data;
block->length = op->number;
(void) tsearch (block, cache, loc_compare);
}
@@ -412,11 +414,11 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
if (unlikely (dbg == NULL))
goto invalid;
+ newloc->number2 = (Dwarf_Word) data; /* start of block inc. len. */
/* XXX Check size. */
get_uleb128 (newloc->number, data); /* Block length. */
if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number))
goto invalid;
- newloc->number2 = data - block->data; /* Relative block offset. */
data += newloc->number; /* Skip the block. */
break;
@@ -437,17 +439,20 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
break;
case DW_OP_GNU_const_type:
- /* XXX Check size. */
- get_uleb128 (newloc->number, data);
- if (unlikely (data >= end_data))
- goto invalid;
- newloc->number2 = *data++; /* Block length. */
- if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number2))
- goto invalid;
- /* The third operand is relative block offset:
- newloc->number3 = data - block->data;
- We don't support this at this point. */
- data += newloc->number2; /* Skip the block. */
+ {
+ size_t size;
+
+ /* XXX Check size. */
+ get_uleb128 (newloc->number, data);
+ if (unlikely (data >= end_data))
+ goto invalid;
+
+ newloc->number2 = (Dwarf_Word) data; /* start of block inc. len. */
+ size = *data++;
+ if (unlikely ((Dwarf_Word) (end_data - data) < size))
+ goto invalid;
+ data += size; /* Skip the block. */
+ }
break;
default:
@@ -505,7 +510,7 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
result[n].offset = loclist->offset;
if (result[n].atom == DW_OP_implicit_value)
- store_implicit_value (dbg, cache, &result[n], block->data);
+ store_implicit_value (dbg, cache, &result[n]);
loclist = loclist->next;
}
diff --git a/libdw/dwarf_getlocation_attr.c b/libdw/dwarf_getlocation_attr.c
new file mode 100644
index 0000000..2d6084e
--- /dev/null
+++ b/libdw/dwarf_getlocation_attr.c
@@ -0,0 +1,103 @@
+/* Return DWARF attribute associated with a location expression op.
+ Copyright (C) 2013 Red Hat, Inc.
+ This file is part of elfutils.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of either
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at
+ your option) any later version
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at
+ your option) any later version
+
+ or both in parallel, as here.
+
+ elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <libdwP.h>
+
+
+int
+dwarf_getlocation_attr (attr, op, result)
+ Dwarf_Attribute *attr;
+ const Dwarf_Op *op;
+ Dwarf_Attribute *result;
+{
+ if (attr == NULL)
+ return -1;
+
+ result->cu = attr->cu;
+
+ switch (op->atom)
+ {
+ case DW_OP_implicit_value:
+ result->code = DW_AT_const_value;
+ result->form = DW_FORM_block;
+ result->valp = (unsigned char *) op->number2;
+ break;
+
+ case DW_OP_GNU_entry_value:
+ result->code = DW_AT_location;
+ result->form = DW_FORM_exprloc;
+ result->valp = (unsigned char *) op->number2;
+ break;
+
+ case DW_OP_GNU_const_type:
+ result->code = DW_AT_const_value;
+ result->form = DW_FORM_block1;
+ result->valp = (unsigned char *) op->number2;
+ break;
+
+ case DW_OP_call2:
+ case DW_OP_call4:
+ case DW_OP_call_ref:
+ {
+ Dwarf_Die die;
+ if (INTUSE(dwarf_getlocation_die) (attr, op, &die) != 0)
+ return -1;
+ if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+ }
+ }
+ break;
+
+ case DW_OP_GNU_implicit_pointer:
+ {
+ Dwarf_Die die;
+ if (INTUSE(dwarf_getlocation_die) (attr, op, &die) != 0)
+ return -1;
+ if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL
+ && INTUSE(dwarf_attr) (&die, DW_AT_const_value, result) == NULL)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+ }
+ }
+ break;
+
+ default:
+ __libdw_seterrno (DWARF_E_INVALID_ACCESS);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/libdw/dwarf_getlocation_die.c b/libdw/dwarf_getlocation_die.c
new file mode 100644
index 0000000..fa03aac
--- /dev/null
+++ b/libdw/dwarf_getlocation_die.c
@@ -0,0 +1,78 @@
+/* Return DIE associated with a location expression op.
+ Copyright (C) 2013 Red Hat, Inc.
+ This file is part of elfutils.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of either
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at
+ your option) any later version
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at
+ your option) any later version
+
+ or both in parallel, as here.
+
+ elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <libdwP.h>
+
+int
+dwarf_getlocation_die (attr, op, result)
+ Dwarf_Attribute *attr;
+ const Dwarf_Op *op;
+ Dwarf_Die *result;
+{
+ if (attr == NULL)
+ return -1;
+
+ Dwarf_Off dieoff;
+ switch (op->atom)
+ {
+ case DW_OP_GNU_implicit_pointer:
+ case DW_OP_call_ref:
+ dieoff = op->number;
+ break;
+
+ case DW_OP_GNU_parameter_ref:
+ case DW_OP_GNU_convert:
+ case DW_OP_GNU_reinterpret:
+ case DW_OP_GNU_const_type:
+ case DW_OP_call2:
+ case DW_OP_call4:
+ dieoff = attr->cu->start + op->number;
+ break;
+
+ case DW_OP_GNU_regval_type:
+ case DW_OP_GNU_deref_type:
+ dieoff = attr->cu->start + op->number2;
+ break;
+
+ default:
+ __libdw_seterrno (DWARF_E_INVALID_ACCESS);
+ return -1;
+ }
+
+ if (__libdw_offdie (attr->cu->dbg, dieoff, result,
+ attr->cu->type_offset != 0) == NULL)
+ return -1;
+
+ return 0;
+}
+INTDEF(dwarf_getlocation_die);
diff --git a/libdw/libdw.h b/libdw/libdw.h
index 898aa74..d1cd177 100644
--- a/libdw/libdw.h
+++ b/libdw/libdw.h
@@ -664,6 +664,29 @@ extern int dwarf_getlocation_implicit_pointer (Dwarf_Attribute *attr,
Dwarf_Attribute *result)
__nonnull_attribute__ (2, 3);
+/* Return the DIE associated with an operation such as
+ DW_OP_GNU_implicit_pointer, DW_OP_GNU_parameter_ref, DW_OP_GNU_convert,
+ DW_OP_GNU_reinterpret, DW_OP_GNU_const_type, DW_OP_GNU_regval_type or
+ DW_OP_GNU_deref_type. The OP pointer must point into an expression that
+ dwarf_getlocation or dwarf_getlocation_addr has returned given the same
+ ATTR. The RESULT is a DIE that expresses a type or value needed by the
+ given OP. */
+extern int dwarf_getlocation_die (Dwarf_Attribute *attr,
+ const Dwarf_Op *op,
+ Dwarf_Die *result)
+ __nonnull_attribute__ (2, 3);
+
+/* Return the attribute expressing a value associated with an operation such
+ as DW_OP_implicit_value, DW_OP_GNU_entry_value or DW_OP_GNU_const_type.
+ The OP pointer must point into an expression that dwarf_getlocation
+ or dwarf_getlocation_addr has returned given the same ATTR.
+ The RESULT is a value expressed by an attribute such as DW_AT_location
+ or DW_AT_const_value. */
+extern int dwarf_getlocation_attr (Dwarf_Attribute *attr,
+ const Dwarf_Op *op,
+ Dwarf_Attribute *result)
+ __nonnull_attribute__ (2, 3);
+
/* Compute the byte-size of a type DIE according to DWARF rules.
For most types, this is just DW_AT_byte_size.
diff --git a/libdw/libdw.map b/libdw/libdw.map
index 2d2d37c..09eae6a 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -264,4 +264,6 @@ ELFUTILS_0.156 {
ELFUTILS_0.157 {
global:
dwarf_getlocations;
+ dwarf_getlocation_die;
+ dwarf_getlocation_attr;
} ELFUTILS_0.156;
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 76bddff..f02a5bf 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -1,5 +1,5 @@
/* Internal definitions for libdwarf.
- Copyright (C) 2002-2011 Red Hat, Inc.
+ Copyright (C) 2002-2011, 2013 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper(a)redhat.com>, 2002.
@@ -654,6 +654,7 @@ INTDECL (dwarf_formudata)
INTDECL (dwarf_getarange_addr)
INTDECL (dwarf_getarangeinfo)
INTDECL (dwarf_getaranges)
+INTDECL (dwarf_getlocation_die)
INTDECL (dwarf_getsrcfiles)
INTDECL (dwarf_getsrclines)
INTDECL (dwarf_hasattr)
--
1.8.3.1
10 years, 7 months