[PATCH] Fix section corruption bug
by Thilo Schulz
Hi,
When adding data to existing sections in ELF files, libelf may corrupt
those sections, i.e. overwrite the existing data if certain conditions are
met.
If an Elf_Scn structure has seen a call to elf_rawdata(scn) before but no
call to elf_getdata(scn), scn->read_data flag is set, but not
scn->data_list_rear.
Thus, elf_newdata(scn) incorrectly detects a "new user added section" when
really it is a section with live, valid data that will be overwritten by
elf_update(), corrupting the section.
This patch fixes this incorrect behaviour.
Signed-off-by: Thilo Schulz <thilo(a)tjps.eu>
---
libelf/elf_newdata.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libelf/elf_newdata.c b/libelf/elf_newdata.c
index 90d1813..f90eb0a 100644
--- a/libelf/elf_newdata.c
+++ b/libelf/elf_newdata.c
@@ -64,7 +64,7 @@ elf_newdata (Elf_Scn *scn)
rwlock_wrlock (scn->elf->lock);
- if (scn->data_read && scn->data_list_rear == NULL)
+ if (scn->data_read && scn->data_list_rear == NULL && !scn->rawdata.s)
{
/* This means the section was created by the user and this is the
first data. */
--
1.7.10.4
8 years, 9 months
[PATCH] aarch64: use <sys/user.h> defined register structures
by Kyle McMartin
glibc now supplies these (compatible) structs instead of including the
kernel's <asm/ptrace.h> header, so let's use them. Annoyingly this will
cause new elfutils to FTBFS on old glibc, and vice versa, but that seems
unavoidable in the growth of a new port, and the workaround of checking
for header defines and defining one to the other seems unpleasant as
well. Therefore, bite the bullet, and let packaging systems alter their
build requires accordingly.
--- a/backends/aarch64_initreg.c
+++ b/backends/aarch64_initreg.c
@@ -51,7 +51,7 @@ aarch64_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
#else /* __aarch64__ */
/* General registers. */
- struct user_pt_regs gregs;
+ struct user_regs_struct gregs;
struct iovec iovec;
iovec.iov_base = &gregs;
iovec.iov_len = sizeof (gregs);
@@ -69,7 +69,7 @@ aarch64_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
/* ELR cannot be found. */
/* FP registers (only 64bits are used). */
- struct user_fpsimd_state fregs;
+ struct user_fpsimd_struct fregs;
iovec.iov_base = &fregs;
iovec.iov_len = sizeof (fregs);
if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, &iovec) != 0)
diff --git a/backends/arm_initreg.c b/backends/arm_initreg.c
index 5837383..1edf62b 100644
--- a/backends/arm_initreg.c
+++ b/backends/arm_initreg.c
@@ -67,7 +67,7 @@ arm_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
#elif defined __aarch64__
/* Compat mode: arm compatible code running on aarch64 */
int i;
- struct user_pt_regs gregs;
+ struct user_regs_struct gregs;
struct iovec iovec;
iovec.iov_base = &gregs;
iovec.iov_len = sizeof (gregs);
9 years, 4 months
[PATCH] Make the attach code build again on non-Linux hosts.
by Kurt Roeckx
Signed-off-by: Kurt Roeckx <kurt(a)roeckx.be>
---
libdwfl/ChangeLog | 4 ++++
libdwfl/linux-pid-attach.c | 17 +++++++++++++++++
2 files changed, 21 insertions(+)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index e11b7d1..4a1b9d5 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,7 @@
+2014-06-24 Kurt Roeckx <kurt(a)roeckx.be>
+
+ * linux-pid-attach.c: Make it build on non linux hosts.
+
2014-06-17 Mark Wielaard <mjw(a)redhat.com>
* frame_unwind.c (handle_cfi): Use ebl_func_addr_mask.
diff --git a/libdwfl/linux-pid-attach.c b/libdwfl/linux-pid-attach.c
index d60955e..ae71702 100644
--- a/libdwfl/linux-pid-attach.c
+++ b/libdwfl/linux-pid-attach.c
@@ -396,6 +396,16 @@ pid_getthread (Dwfl *dwfl __attribute__ ((unused)),
return false;
}
+bool
+internal_function
+__libdwfl_ptrace_attach (pid_t tid __attribute__ ((unused)),
+ bool *tid_was_stoppedp __attribute__ ((unused)))
+{
+ errno = ENOSYS;
+ __libdwfl_seterrno (DWFL_E_ERRNO);
+ return false;
+}
+
static bool
pid_memory_read (Dwfl *dwfl __attribute__ ((unused)),
Dwarf_Addr addr __attribute__ ((unused)),
@@ -422,6 +432,13 @@ pid_detach (Dwfl *dwfl __attribute__ ((unused)),
{
}
+void
+internal_function
+__libdwfl_ptrace_detach (pid_t tid __attribute__ ((unused)),
+ bool tid_was_stopped __attribute__ ((unused)))
+{
+}
+
static void
pid_thread_detach (Dwfl_Thread *thread __attribute__ ((unused)),
void *thread_arg __attribute__ ((unused)))
--
2.0.0
9 years, 5 months
[PATCH] dwarf.h: Remove non-existing DW_TAG_mutable_type.
by Mark Wielaard
The DW_TAG_mutable_type was only mentioned in an early draft of DWARFv3.
But was removed because there are no C++ mutable qualified types. It was
replaced by a new attribute DW_AT_mutable on DW_TAG_member DIEs. The new
attribute is available in dwarf.h.
http://dwarfstd.org/ShowIssue.php?issue=050223.1
DW_TAG_mutable_type was only used internally in some backends (which
just ignored it anyway). dwarves did use it to turn it into a string
value, libabigail used it and ignored it (patches to remove sent).
GCC, GDB and binutils don't use nor define it.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
backends/alpha_retval.c | 2 +-
backends/arm_retval.c | 2 +-
backends/i386_retval.c | 2 +-
backends/ia64_retval.c | 2 +-
backends/libebl_CPU.h | 2 +-
backends/ppc64_retval.c | 2 +-
backends/ppc_retval.c | 2 +-
backends/s390_retval.c | 2 +-
backends/sh_retval.c | 2 +-
backends/sparc_retval.c | 2 +-
backends/tilegx_retval.c | 2 +-
backends/x86_64_retval.c | 2 +-
libdw/dwarf.h | 1 -
13 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/backends/alpha_retval.c b/backends/alpha_retval.c
index 6dfa694..fddb47f 100644
--- a/backends/alpha_retval.c
+++ b/backends/alpha_retval.c
@@ -82,7 +82,7 @@ alpha_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
|| tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
+ || tag == DW_TAG_restrict_type)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
diff --git a/backends/arm_retval.c b/backends/arm_retval.c
index 222f755..92e3631 100644
--- a/backends/arm_retval.c
+++ b/backends/arm_retval.c
@@ -78,7 +78,7 @@ arm_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
|| tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
+ || tag == DW_TAG_restrict_type)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
diff --git a/backends/i386_retval.c b/backends/i386_retval.c
index 90678c3..dc0c5e6 100644
--- a/backends/i386_retval.c
+++ b/backends/i386_retval.c
@@ -82,7 +82,7 @@ i386_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
|| tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
+ || tag == DW_TAG_restrict_type)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
diff --git a/backends/ia64_retval.c b/backends/ia64_retval.c
index ac0d8c3..d259a80 100644
--- a/backends/ia64_retval.c
+++ b/backends/ia64_retval.c
@@ -253,7 +253,7 @@ ia64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
|| tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
+ || tag == DW_TAG_restrict_type)
{
attr = dwarf_attr (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
diff --git a/backends/libebl_CPU.h b/backends/libebl_CPU.h
index 3ad9258..344a70e 100644
--- a/backends/libebl_CPU.h
+++ b/backends/libebl_CPU.h
@@ -60,7 +60,7 @@ dwarf_peel_type (Dwarf_Die *typediep, Dwarf_Attribute *attrp)
int tag = DWARF_TAG_OR_RETURN (typediep);
while (tag == DW_TAG_typedef
|| tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
+ || tag == DW_TAG_restrict_type)
{
attrp = dwarf_attr_integrate (typediep, DW_AT_type, attrp);
typediep = dwarf_formref_die (attrp, typediep);
diff --git a/backends/ppc64_retval.c b/backends/ppc64_retval.c
index c5c3b6f..042859f 100644
--- a/backends/ppc64_retval.c
+++ b/backends/ppc64_retval.c
@@ -92,7 +92,7 @@ ppc64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
|| tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
+ || tag == DW_TAG_restrict_type)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
diff --git a/backends/ppc_retval.c b/backends/ppc_retval.c
index 7ca0c18..c289440 100644
--- a/backends/ppc_retval.c
+++ b/backends/ppc_retval.c
@@ -104,7 +104,7 @@ ppc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
|| tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
+ || tag == DW_TAG_restrict_type)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
diff --git a/backends/s390_retval.c b/backends/s390_retval.c
index b671ee8..f830f0e 100644
--- a/backends/s390_retval.c
+++ b/backends/s390_retval.c
@@ -83,7 +83,7 @@ s390_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
|| tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
+ || tag == DW_TAG_restrict_type)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
diff --git a/backends/sh_retval.c b/backends/sh_retval.c
index 1166231..c45c91a 100644
--- a/backends/sh_retval.c
+++ b/backends/sh_retval.c
@@ -80,7 +80,7 @@ sh_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
|| tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
+ || tag == DW_TAG_restrict_type)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
diff --git a/backends/sparc_retval.c b/backends/sparc_retval.c
index dcd3785..91b97fd 100644
--- a/backends/sparc_retval.c
+++ b/backends/sparc_retval.c
@@ -87,7 +87,7 @@ sparc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
|| tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
+ || tag == DW_TAG_restrict_type)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
diff --git a/backends/tilegx_retval.c b/backends/tilegx_retval.c
index e14cc51..25fbc9a 100644
--- a/backends/tilegx_retval.c
+++ b/backends/tilegx_retval.c
@@ -74,7 +74,7 @@ tilegx_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
|| tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
+ || tag == DW_TAG_restrict_type)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
diff --git a/backends/x86_64_retval.c b/backends/x86_64_retval.c
index f3e9f2b..5734afc 100644
--- a/backends/x86_64_retval.c
+++ b/backends/x86_64_retval.c
@@ -96,7 +96,7 @@ x86_64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
|| tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
+ || tag == DW_TAG_restrict_type)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
diff --git a/libdw/dwarf.h b/libdw/dwarf.h
index 41cae5b..a8d2ec9 100644
--- a/libdw/dwarf.h
+++ b/libdw/dwarf.h
@@ -87,7 +87,6 @@ enum
DW_TAG_unspecified_type = 0x3b,
DW_TAG_partial_unit = 0x3c,
DW_TAG_imported_unit = 0x3d,
- DW_TAG_mutable_type = 0x3e,
DW_TAG_condition = 0x3f,
DW_TAG_shared_type = 0x40,
DW_TAG_type_unit = 0x41,
--
1.7.1
9 years, 5 months
[PATCH] libebl: Add ebl_unwind_ret_mask.
by Mark Wielaard
Another ARM oddity. A return value address in an unwind will contain an
extra bit to indicate whether to return to a regular ARM or THUMB function.
Add a new ebl function to return a mask to use to get the actual return
address during an unwind ebl_unwind_ret_mask.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
backends/ChangeLog | 4 ++++
backends/arm_init.c | 3 +++
libdwfl/ChangeLog | 4 ++++
libdwfl/frame_unwind.c | 6 +++++-
libebl/ChangeLog | 6 ++++++
libebl/eblinitreg.c | 9 ++++++++-
libebl/libebl.h | 4 ++++
libebl/libeblP.h | 8 +++++++-
8 files changed, 41 insertions(+), 3 deletions(-)
diff --git a/backends/ChangeLog b/backends/ChangeLog
index 64b669e..11538b0 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,7 @@
+2014-06-15 Mark Wielaard <mjw(a)redhat.com>
+
+ * arm_init.c (arm_init): Set unwind_ret_mask.
+
2014-06-14 Mark Wielaard <mjw(a)redhat.com>
* arm_init.c (arm_init): Hook sym_func_value.
diff --git a/backends/arm_init.c b/backends/arm_init.c
index e2e20e4..f95949d 100644
--- a/backends/arm_init.c
+++ b/backends/arm_init.c
@@ -70,5 +70,8 @@ arm_init (elf, machine, eh, ehlen)
eh->frame_nregs = 16;
HOOK (eh, set_initial_registers_tid);
+ /* Bit zero encodes whether to return to a THUMB or ARM function. */
+ eh->unwind_ret_mask = ~(GElf_Addr)1;
+
return MODVERSION;
}
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 888b400..195f5a0 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,7 @@
+2014-06-15 Mark Wielaard <mjw(a)redhat.com>
+
+ * frame_unwind.c (handle_cfi): Use ebl_unwind_ret_mask.
+
2014-06-14 Mark Wielaard <mjw(a)redhat.com>
* dwfl_module_getsym.c (__libdwfl_getsym): Call ebl_sym_func_value.
diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c
index 18c808b..f93348f 100644
--- a/libdwfl/frame_unwind.c
+++ b/libdwfl/frame_unwind.c
@@ -1,5 +1,5 @@
/* Get previous frame state for an existing frame state.
- Copyright (C) 2013 Red Hat, Inc.
+ Copyright (C) 2013, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -582,6 +582,10 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias)
continue;
}
+ /* Some architectures encode some extra info in the return address. */
+ if (regno == frame->fde->cie->return_address_register)
+ regval &= ebl_unwind_ret_mask (ebl);
+
/* This is another strange PPC[64] case. There are two
registers numbers that can represent the same DWARF return
register number. We only want one to actually set the return
diff --git a/libebl/ChangeLog b/libebl/ChangeLog
index 1c7a2ba..d5fac1d 100644
--- a/libebl/ChangeLog
+++ b/libebl/ChangeLog
@@ -1,3 +1,9 @@
+2014-06-15 Mark Wielaard <mjw(a)redhat.com>
+
+ * eblinitreg.c (ebl_unwind_ret_mask): New function.
+ * libebl.h (ebl_unwind_ret_mask): Define.
+ * libeblP.h (struct ebl): Add unwind_ret_mask.
+
2014-06-14 Mark Wielaard <mjw(a)redhat.com>
* Makefile.am (gen_SOURCES): Add eblsymfuncval.c.
diff --git a/libebl/eblinitreg.c b/libebl/eblinitreg.c
index 8909c50..a6bb00c 100644
--- a/libebl/eblinitreg.c
+++ b/libebl/eblinitreg.c
@@ -1,5 +1,5 @@
/* Fetch live process Dwfl_Frame from PID.
- Copyright (C) 2013 Red Hat, Inc.
+ Copyright (C) 2013, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -49,3 +49,10 @@ ebl_frame_nregs (Ebl *ebl)
{
return ebl == NULL ? 0 : ebl->frame_nregs;
}
+
+GElf_Addr
+ebl_unwind_ret_mask (Ebl *ebl)
+{
+ return ((ebl == NULL || ebl->unwind_ret_mask == 0)
+ ? ~(GElf_Addr)0 : ebl->unwind_ret_mask);
+}
diff --git a/libebl/libebl.h b/libebl/libebl.h
index bc1f491..768dab4 100644
--- a/libebl/libebl.h
+++ b/libebl/libebl.h
@@ -409,6 +409,10 @@ extern bool ebl_set_initial_registers_tid (Ebl *ebl,
extern size_t ebl_frame_nregs (Ebl *ebl)
__nonnull_attribute__ (1);
+/* Mask to use for unwind return address in case the architecture adds
+ some extra non-address bits to it. */
+extern GElf_Addr ebl_unwind_ret_mask (Ebl *ebl);
+
/* Convert *REGNO as is in DWARF to a lower range suitable for
Dwarf_Frame->REGS indexing. */
extern bool ebl_dwarf_to_regno (Ebl *ebl, unsigned *regno)
diff --git a/libebl/libeblP.h b/libebl/libeblP.h
index f91c2a0..ac38258 100644
--- a/libebl/libeblP.h
+++ b/libebl/libeblP.h
@@ -1,5 +1,5 @@
/* Internal definitions for interface for libebl.
- Copyright (C) 2000-2009, 2013 Red Hat, Inc.
+ Copyright (C) 2000-2009, 2013, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -64,6 +64,12 @@ struct ebl
Ebl architecture can unwind iff FRAME_NREGS > 0. */
size_t frame_nregs;
+ /* Mask to use to get the return address from an unwind in case the
+ architecture adds some extra non-address bits to it. When not
+ initialized (0) then ebl_unwind_ret_mask will return ~0, otherwise
+ it should be the actual mask to use. */
+ GElf_Addr unwind_ret_mask;
+
/* Function descriptor load address and table as used by
ebl_resolve_sym_value if available for this arch. */
GElf_Addr fd_addr;
--
1.9.3
9 years, 5 months
[PATCH] backends (*_return_value_location): call dwarf_peeled_die_type
by Petr Machata
... instead of inlining equivalent code.
Signed-off-by: Petr Machata <pmachata(a)redhat.com>
---
backends/ChangeLog | 15 ++++++++++
backends/alpha_retval.c | 29 +++++---------------
backends/arm_retval.c | 67 ++++++++++++++++++---------------------------
backends/i386_retval.c | 29 +++++---------------
backends/ia64_retval.c | 49 +++++++++++++--------------------
backends/ppc64_retval.c | 49 +++++++++++++--------------------
backends/ppc_retval.c | 50 +++++++++++++--------------------
backends/s390_retval.c | 29 +++++---------------
backends/sh_retval.c | 49 +++++++++++++--------------------
backends/sparc_retval.c | 55 +++++++++++++++----------------------
backends/tilegx_retval.c | 63 ++++++++++++++++++-------------------------
backends/x86_64_retval.c | 49 +++++++++++++--------------------
12 files changed, 208 insertions(+), 325 deletions(-)
diff --git a/backends/ChangeLog b/backends/ChangeLog
index bc5b843..7eda035 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,18 @@
+2014-06-20 Petr Machata <pmachata(a)redhat.com>
+
+ * alpha_retval.c (alpha_return_value_location): Call
+ dwarf_peeled_die_type instead of inlining equivalent code.
+ * arm_retval.c (arm_return_value_location): Likewise.
+ * i386_retval.c (i386_return_value_location): Likewise.
+ * ia64_retval.c (ia64_return_value_location): Likewise.
+ * ppc64_retval.c (ppc64_return_value_location): Likewise.
+ * ppc_retval.c (ppc_return_value_location): Likewise.
+ * s390_retval.c (s390_return_value_location): Likewise.
+ * sh_retval.c (sh_return_value_location): Likewise.
+ * sparc_retval.c (sparc_return_value_location): Likewise.
+ * tilegx_retval.c (tilegx_return_value_location): Likewise.
+ * x86_64_retval.c (x86_64_return_value_location): Likewise.
+
2014-05-19 Mark Wielaard <mjw(a)redhat.com>
* arm_init.c (arm_init): Hook check_reloc_target_type.
diff --git a/backends/alpha_retval.c b/backends/alpha_retval.c
index 6dfa694..53dbfa4 100644
--- a/backends/alpha_retval.c
+++ b/backends/alpha_retval.c
@@ -1,5 +1,5 @@
/* Function return value location for Alpha ELF ABI.
- Copyright (C) 2005, 2007 Red Hat, Inc.
+ Copyright (C) 2005, 2007, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -67,27 +67,10 @@ alpha_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
/* Start with the function's type, and get the DW_AT_type attribute,
which is the type of the return value. */
-
- Dwarf_Attribute attr_mem;
- Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type,
- &attr_mem);
- if (attr == NULL)
- /* The function has no return value, like a `void' function in C. */
- return 0;
-
- Dwarf_Die die_mem;
- Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = DWARF_TAG_OR_RETURN (typedie);
-
- /* Follow typedefs and qualifiers to get to the actual type. */
- while (tag == DW_TAG_typedef
- || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
- {
- attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
- typedie = dwarf_formref_die (attr, &die_mem);
- tag = DWARF_TAG_OR_RETURN (typedie);
- }
+ Dwarf_Die die_mem, *typedie = &die_mem;
+ int tag = dwarf_peeled_die_type (functypedie, typedie);
+ if (tag <= 0)
+ return tag;
switch (tag)
{
@@ -97,6 +80,7 @@ alpha_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_subrange_type:
if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
{
+ Dwarf_Attribute attr_mem, *attr;
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
tag = DWARF_TAG_OR_RETURN (typedie);
@@ -108,6 +92,7 @@ alpha_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_pointer_type:
case DW_TAG_ptr_to_member_type:
{
+ Dwarf_Attribute attr_mem;
Dwarf_Word size;
if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
&attr_mem), &size) != 0)
diff --git a/backends/arm_retval.c b/backends/arm_retval.c
index 222f755..7aced74 100644
--- a/backends/arm_retval.c
+++ b/backends/arm_retval.c
@@ -1,5 +1,5 @@
/* Function return value location for ARM EABI.
- Copyright (C) 2009-2010 Red Hat, Inc.
+ Copyright (C) 2009-2010, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -63,27 +63,10 @@ arm_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
/* Start with the function's type, and get the DW_AT_type attribute,
which is the type of the return value. */
-
- Dwarf_Attribute attr_mem;
- Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type,
- &attr_mem);
- if (attr == NULL)
- /* The function has no return value, like a `void' function in C. */
- return 0;
-
- Dwarf_Die die_mem;
- Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = DWARF_TAG_OR_RETURN (typedie);
-
- /* Follow typedefs and qualifiers to get to the actual type. */
- while (tag == DW_TAG_typedef
- || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
- {
- attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
- typedie = dwarf_formref_die (attr, &die_mem);
- tag = DWARF_TAG_OR_RETURN (typedie);
- }
+ Dwarf_Die die_mem, *typedie = &die_mem;
+ int tag = dwarf_peeled_die_type (functypedie, typedie);
+ if (tag <= 0)
+ return tag;
Dwarf_Word size;
switch (tag)
@@ -94,6 +77,7 @@ arm_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_subrange_type:
if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
{
+ Dwarf_Attribute attr_mem, *attr;
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
tag = DWARF_TAG_OR_RETURN (typedie);
@@ -104,24 +88,27 @@ arm_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_enumeration_type:
case DW_TAG_pointer_type:
case DW_TAG_ptr_to_member_type:
- if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
- &attr_mem), &size) != 0)
- {
- if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
- size = 4;
- else
- return -1;
- }
- if (size <= 16)
- {
- intreg:
- *locp = loc_intreg;
- return size <= 4 ? nloc_intreg : nloc_intregs ((size + 3) / 4);
- }
-
- aggregate:
- *locp = loc_aggregate;
- return nloc_aggregate;
+ {
+ Dwarf_Attribute attr_mem;
+ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+ &attr_mem), &size) != 0)
+ {
+ if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+ size = 4;
+ else
+ return -1;
+ }
+ if (size <= 16)
+ {
+ intreg:
+ *locp = loc_intreg;
+ return size <= 4 ? nloc_intreg : nloc_intregs ((size + 3) / 4);
+ }
+
+ aggregate:
+ *locp = loc_aggregate;
+ return nloc_aggregate;
+ }
case DW_TAG_structure_type:
case DW_TAG_class_type:
diff --git a/backends/i386_retval.c b/backends/i386_retval.c
index 90678c3..9da797d 100644
--- a/backends/i386_retval.c
+++ b/backends/i386_retval.c
@@ -1,5 +1,5 @@
/* Function return value location for Linux/i386 ABI.
- Copyright (C) 2005-2010 Red Hat, Inc.
+ Copyright (C) 2005-2010, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -67,27 +67,10 @@ i386_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
/* Start with the function's type, and get the DW_AT_type attribute,
which is the type of the return value. */
-
- Dwarf_Attribute attr_mem;
- Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type,
- &attr_mem);
- if (attr == NULL)
- /* The function has no return value, like a `void' function in C. */
- return 0;
-
- Dwarf_Die die_mem;
- Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = DWARF_TAG_OR_RETURN (typedie);
-
- /* Follow typedefs and qualifiers to get to the actual type. */
- while (tag == DW_TAG_typedef
- || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
- {
- attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
- typedie = dwarf_formref_die (attr, &die_mem);
- tag = DWARF_TAG_OR_RETURN (typedie);
- }
+ Dwarf_Die die_mem, *typedie = &die_mem;
+ int tag = dwarf_peeled_die_type (functypedie, typedie);
+ if (tag <= 0)
+ return tag;
switch (tag)
{
@@ -97,6 +80,7 @@ i386_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_subrange_type:
if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
{
+ Dwarf_Attribute attr_mem, *attr;
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
tag = DWARF_TAG_OR_RETURN (typedie);
@@ -109,6 +93,7 @@ i386_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_ptr_to_member_type:
{
Dwarf_Word size;
+ Dwarf_Attribute attr_mem;
if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
&attr_mem), &size) != 0)
{
diff --git a/backends/ia64_retval.c b/backends/ia64_retval.c
index ac0d8c3..b5928c5 100644
--- a/backends/ia64_retval.c
+++ b/backends/ia64_retval.c
@@ -1,5 +1,5 @@
/* Function return value location for IA64 ABI.
- Copyright (C) 2006-2010 Red Hat, Inc.
+ Copyright (C) 2006-2010, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -238,27 +238,10 @@ ia64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
/* Start with the function's type, and get the DW_AT_type attribute,
which is the type of the return value. */
-
- Dwarf_Attribute attr_mem;
- Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type,
- &attr_mem);
- if (attr == NULL)
- /* The function has no return value, like a `void' function in C. */
- return 0;
-
- Dwarf_Die die_mem;
- Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = DWARF_TAG_OR_RETURN (typedie);
-
- /* Follow typedefs and qualifiers to get to the actual type. */
- while (tag == DW_TAG_typedef
- || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
- {
- attr = dwarf_attr (typedie, DW_AT_type, &attr_mem);
- typedie = dwarf_formref_die (attr, &die_mem);
- tag = DWARF_TAG_OR_RETURN (typedie);
- }
+ Dwarf_Die die_mem, *typedie = &die_mem;
+ int tag = dwarf_peeled_die_type (functypedie, typedie);
+ if (tag <= 0)
+ return tag;
Dwarf_Word size;
switch (tag)
@@ -269,6 +252,7 @@ ia64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_subrange_type:
if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
{
+ Dwarf_Attribute attr_mem, *attr;
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
tag = DWARF_TAG_OR_RETURN (typedie);
@@ -279,16 +263,21 @@ ia64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_enumeration_type:
case DW_TAG_pointer_type:
case DW_TAG_ptr_to_member_type:
- if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
- &attr_mem), &size) != 0)
- {
- if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
- size = 8;
- else
- return -1;
- }
+ {
+ Dwarf_Attribute attr_mem;
+ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+ &attr_mem), &size) != 0)
+ {
+ if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+ size = 8;
+ else
+ return -1;
+ }
+ }
+
if (tag == DW_TAG_base_type)
{
+ Dwarf_Attribute attr_mem;
Dwarf_Word encoding;
if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
&attr_mem),
diff --git a/backends/ppc64_retval.c b/backends/ppc64_retval.c
index c5c3b6f..a251983 100644
--- a/backends/ppc64_retval.c
+++ b/backends/ppc64_retval.c
@@ -1,5 +1,5 @@
/* Function return value location for Linux/PPC64 ABI.
- Copyright (C) 2005-2010 Red Hat, Inc.
+ Copyright (C) 2005-2010, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -77,27 +77,10 @@ ppc64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
/* Start with the function's type, and get the DW_AT_type attribute,
which is the type of the return value. */
-
- Dwarf_Attribute attr_mem;
- Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type,
- &attr_mem);
- if (attr == NULL)
- /* The function has no return value, like a `void' function in C. */
- return 0;
-
- Dwarf_Die die_mem;
- Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = DWARF_TAG_OR_RETURN (typedie);
-
- /* Follow typedefs and qualifiers to get to the actual type. */
- while (tag == DW_TAG_typedef
- || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
- {
- attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
- typedie = dwarf_formref_die (attr, &die_mem);
- tag = DWARF_TAG_OR_RETURN (typedie);
- }
+ Dwarf_Die die_mem, *typedie = &die_mem;
+ int tag = dwarf_peeled_die_type (functypedie, typedie);
+ if (tag <= 0)
+ return tag;
Dwarf_Word size;
switch (tag)
@@ -108,6 +91,7 @@ ppc64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_subrange_type:
if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
{
+ Dwarf_Attribute attr_mem, *attr;
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
tag = DWARF_TAG_OR_RETURN (typedie);
@@ -118,16 +102,21 @@ ppc64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_enumeration_type:
case DW_TAG_pointer_type:
case DW_TAG_ptr_to_member_type:
- if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
- &attr_mem), &size) != 0)
- {
- if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
- size = 8;
- else
- return -1;
+ {
+ Dwarf_Attribute attr_mem;
+ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+ &attr_mem), &size) != 0)
+ {
+ if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+ size = 8;
+ else
+ return -1;
}
+ }
+
if (tag == DW_TAG_base_type)
{
+ Dwarf_Attribute attr_mem;
Dwarf_Word encoding;
if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
&attr_mem),
@@ -162,6 +151,7 @@ ppc64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_array_type:
{
+ Dwarf_Attribute attr_mem;
bool is_vector;
if (dwarf_formflag (dwarf_attr_integrate (typedie, DW_AT_GNU_vector,
&attr_mem), &is_vector) == 0
@@ -179,6 +169,7 @@ ppc64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
if (tag == DW_TAG_array_type)
{
/* Check if it's a character array. */
+ Dwarf_Attribute attr_mem, *attr;
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
tag = DWARF_TAG_OR_RETURN (typedie);
diff --git a/backends/ppc_retval.c b/backends/ppc_retval.c
index 7ca0c18..b14a99f 100644
--- a/backends/ppc_retval.c
+++ b/backends/ppc_retval.c
@@ -1,5 +1,5 @@
/* Function return value location for Linux/PPC ABI.
- Copyright (C) 2005, 2006, 2007, 2010 Red Hat, Inc.
+ Copyright (C) 2005, 2006, 2007, 2010, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -89,27 +89,10 @@ ppc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
/* Start with the function's type, and get the DW_AT_type attribute,
which is the type of the return value. */
-
- Dwarf_Attribute attr_mem;
- Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type,
- &attr_mem);
- if (attr == NULL)
- /* The function has no return value, like a `void' function in C. */
- return 0;
-
- Dwarf_Die die_mem;
- Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = DWARF_TAG_OR_RETURN (typedie);
-
- /* Follow typedefs and qualifiers to get to the actual type. */
- while (tag == DW_TAG_typedef
- || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
- {
- attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
- typedie = dwarf_formref_die (attr, &die_mem);
- tag = DWARF_TAG_OR_RETURN (typedie);
- }
+ Dwarf_Die die_mem, *typedie = &die_mem;
+ int tag = dwarf_peeled_die_type (functypedie, typedie);
+ if (tag <= 0)
+ return tag;
Dwarf_Word size;
switch (tag)
@@ -120,6 +103,7 @@ ppc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_subrange_type:
if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
{
+ Dwarf_Attribute attr_mem, *attr;
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
tag = DWARF_TAG_OR_RETURN (typedie);
@@ -130,18 +114,23 @@ ppc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_enumeration_type:
case DW_TAG_pointer_type:
case DW_TAG_ptr_to_member_type:
- if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
- &attr_mem), &size) != 0)
- {
- if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
- size = 4;
- else
- return -1;
- }
+ {
+ Dwarf_Attribute attr_mem;
+ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+ &attr_mem), &size) != 0)
+ {
+ if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+ size = 4;
+ else
+ return -1;
+ }
+ }
+
if (size <= 8)
{
if (tag == DW_TAG_base_type)
{
+ Dwarf_Attribute attr_mem;
Dwarf_Word encoding;
if (dwarf_formudata (dwarf_attr_integrate (typedie,
DW_AT_encoding,
@@ -165,6 +154,7 @@ ppc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_array_type:
{
+ Dwarf_Attribute attr_mem;
bool is_vector;
if (dwarf_formflag (dwarf_attr_integrate (typedie, DW_AT_GNU_vector,
&attr_mem), &is_vector) == 0
diff --git a/backends/s390_retval.c b/backends/s390_retval.c
index b671ee8..a927d46 100644
--- a/backends/s390_retval.c
+++ b/backends/s390_retval.c
@@ -1,5 +1,5 @@
/* Function return value location for S/390 ABI.
- Copyright (C) 2006, 2007 Red Hat, Inc.
+ Copyright (C) 2006, 2007, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -68,27 +68,10 @@ s390_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
/* Start with the function's type, and get the DW_AT_type attribute,
which is the type of the return value. */
-
- Dwarf_Attribute attr_mem;
- Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type,
- &attr_mem);
- if (attr == NULL)
- /* The function has no return value, like a `void' function in C. */
- return 0;
-
- Dwarf_Die die_mem;
- Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = DWARF_TAG_OR_RETURN (typedie);
-
- /* Follow typedefs and qualifiers to get to the actual type. */
- while (tag == DW_TAG_typedef
- || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
- {
- attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
- typedie = dwarf_formref_die (attr, &die_mem);
- tag = DWARF_TAG_OR_RETURN (typedie);
- }
+ Dwarf_Die die_mem, *typedie = &die_mem;
+ int tag = dwarf_peeled_die_type (functypedie, typedie);
+ if (tag <= 0)
+ return tag;
Dwarf_Word size;
switch (tag)
@@ -99,6 +82,7 @@ s390_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_subrange_type:
if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
{
+ Dwarf_Attribute attr_mem, *attr;
attr = dwarf_attr (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
tag = DWARF_TAG_OR_RETURN (typedie);
@@ -115,6 +99,7 @@ s390_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
if (dwarf_diecu (typedie, &cudie, &asize, NULL) == NULL)
return -1;
+ Dwarf_Attribute attr_mem;
if (dwarf_formudata (dwarf_attr (typedie, DW_AT_byte_size,
&attr_mem), &size) != 0)
{
diff --git a/backends/sh_retval.c b/backends/sh_retval.c
index 1166231..d44f260 100644
--- a/backends/sh_retval.c
+++ b/backends/sh_retval.c
@@ -1,5 +1,5 @@
/* Function return value location for Linux/SH ABI.
- Copyright (C) 2010 Red Hat, Inc.
+ Copyright (C) 2010, 2014 Red Hat, Inc.
This file is part of elfutils.
Contributed by Matt Fleming <matt(a)console-pimps.org>.
@@ -65,27 +65,10 @@ sh_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
/* Start with the function's type, and get the DW_AT_type attribute,
which is the type of the return value. */
-
- Dwarf_Attribute attr_mem;
- Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type,
- &attr_mem);
- if (attr == NULL)
- /* The function has no return value, like a `void' function in C. */
- return 0;
-
- Dwarf_Die die_mem;
- Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = DWARF_TAG_OR_RETURN (typedie);
-
- /* Follow typedefs and qualifiers to get to the actual type. */
- while (tag == DW_TAG_typedef
- || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
- {
- attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
- typedie = dwarf_formref_die (attr, &die_mem);
- tag = DWARF_TAG_OR_RETURN (typedie);
- }
+ Dwarf_Die die_mem, *typedie = &die_mem;
+ int tag = dwarf_peeled_die_type (functypedie, typedie);
+ if (tag <= 0)
+ return tag;
Dwarf_Word size;
switch (tag)
@@ -96,6 +79,7 @@ sh_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_subrange_type:
if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
{
+ Dwarf_Attribute attr_mem, *attr;
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
tag = DWARF_TAG_OR_RETURN (typedie);
@@ -106,18 +90,23 @@ sh_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_enumeration_type:
case DW_TAG_pointer_type:
case DW_TAG_ptr_to_member_type:
- if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
- &attr_mem), &size) != 0)
- {
- if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
- size = 4;
- else
- return -1;
- }
+ {
+ Dwarf_Attribute attr_mem;
+ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+ &attr_mem), &size) != 0)
+ {
+ if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+ size = 4;
+ else
+ return -1;
+ }
+ }
+
if (size <= 8)
{
if (tag == DW_TAG_base_type)
{
+ Dwarf_Attribute attr_mem;
Dwarf_Word encoding;
if (dwarf_formudata (dwarf_attr_integrate (typedie,
DW_AT_encoding,
diff --git a/backends/sparc_retval.c b/backends/sparc_retval.c
index dcd3785..e1b1775 100644
--- a/backends/sparc_retval.c
+++ b/backends/sparc_retval.c
@@ -1,5 +1,5 @@
/* Function return value location for SPARC.
- Copyright (C) 2006-2010 Red Hat, Inc.
+ Copyright (C) 2006-2010, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -72,27 +72,10 @@ sparc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
/* Start with the function's type, and get the DW_AT_type attribute,
which is the type of the return value. */
-
- Dwarf_Attribute attr_mem;
- Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type,
- &attr_mem);
- if (attr == NULL)
- /* The function has no return value, like a `void' function in C. */
- return 0;
-
- Dwarf_Die die_mem;
- Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = DWARF_TAG_OR_RETURN (typedie);
-
- /* Follow typedefs and qualifiers to get to the actual type. */
- while (tag == DW_TAG_typedef
- || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
- {
- attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
- typedie = dwarf_formref_die (attr, &die_mem);
- tag = DWARF_TAG_OR_RETURN (typedie);
- }
+ Dwarf_Die die_mem, *typedie = &die_mem;
+ int tag = dwarf_peeled_die_type (functypedie, typedie);
+ if (tag <= 0)
+ return tag;
Dwarf_Word size;
switch (tag)
@@ -103,6 +86,7 @@ sparc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_subrange_type:
if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
{
+ Dwarf_Attribute attr_mem, *attr;
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
tag = DWARF_TAG_OR_RETURN (typedie);
@@ -113,19 +97,24 @@ sparc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_enumeration_type:
case DW_TAG_pointer_type:
case DW_TAG_ptr_to_member_type:
- if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
- &attr_mem), &size) != 0)
- {
- uint8_t asize;
- Dwarf_Die cudie;
- if ((tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
- && dwarf_diecu (typedie, &cudie, &asize, NULL) != NULL)
- size = asize;
- else
- return -1;
- }
+ {
+ Dwarf_Attribute attr_mem;
+ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+ &attr_mem), &size) != 0)
+ {
+ uint8_t asize;
+ Dwarf_Die cudie;
+ if ((tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+ && dwarf_diecu (typedie, &cudie, &asize, NULL) != NULL)
+ size = asize;
+ else
+ return -1;
+ }
+ }
+
if (tag == DW_TAG_base_type)
{
+ Dwarf_Attribute attr_mem;
Dwarf_Word encoding;
if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
&attr_mem),
diff --git a/backends/tilegx_retval.c b/backends/tilegx_retval.c
index e14cc51..db81a20 100644
--- a/backends/tilegx_retval.c
+++ b/backends/tilegx_retval.c
@@ -1,5 +1,6 @@
/* Function return value location for Linux/TILE-Gx ABI.
Copyright (C) 2012 Tilera Corporation
+ Copyright (C) 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -59,27 +60,10 @@ tilegx_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
/* Start with the function's type, and get the DW_AT_type attribute,
which is the type of the return value. */
-
- Dwarf_Attribute attr_mem;
- Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type,
- &attr_mem);
- if (attr == NULL)
- /* The function has no return value, like a `void' function in C. */
- return 0;
-
- Dwarf_Die die_mem;
- Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = DWARF_TAG_OR_RETURN (typedie);
-
- /* Follow typedefs and qualifiers to get to the actual type. */
- while (tag == DW_TAG_typedef
- || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
- {
- attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
- typedie = dwarf_formref_die (attr, &die_mem);
- tag = DWARF_TAG_OR_RETURN (typedie);
- }
+ Dwarf_Die die_mem, *typedie = &die_mem;
+ int tag = dwarf_peeled_die_type (functypedie, typedie);
+ if (tag <= 0)
+ return tag;
Dwarf_Word size;
switch (tag)
@@ -90,6 +74,7 @@ tilegx_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_subrange_type:
if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
{
+ Dwarf_Attribute attr_mem, *attr;
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
tag = DWARF_TAG_OR_RETURN (typedie);
@@ -100,22 +85,25 @@ tilegx_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_enumeration_type:
case DW_TAG_pointer_type:
case DW_TAG_ptr_to_member_type:
- if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
- &attr_mem), &size) != 0)
- {
- if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
- size = 8;
- else
- return -1;
- }
- if (tag == DW_TAG_base_type)
- {
- Dwarf_Word encoding;
- if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
- &attr_mem),
- &encoding) != 0)
- return -1;
- }
+ {
+ Dwarf_Attribute attr_mem;
+ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+ &attr_mem), &size) != 0)
+ {
+ if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+ size = 8;
+ else
+ return -1;
+ }
+ if (tag == DW_TAG_base_type)
+ {
+ Dwarf_Word encoding;
+ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+ &attr_mem),
+ &encoding) != 0)
+ return -1;
+ }
+ }
/* Small enough structs are passed directly in registers R0 ... R7. */
if (size <= 8)
@@ -139,6 +127,7 @@ tilegx_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
if (tag == DW_TAG_array_type)
{
+ Dwarf_Attribute attr_mem, *attr;
/* Check if it's a character array. */
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
diff --git a/backends/x86_64_retval.c b/backends/x86_64_retval.c
index f3e9f2b..b3799ae 100644
--- a/backends/x86_64_retval.c
+++ b/backends/x86_64_retval.c
@@ -1,5 +1,5 @@
/* Function return value location for Linux/x86-64 ABI.
- Copyright (C) 2005-2010 Red Hat, Inc.
+ Copyright (C) 2005-2010, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -81,27 +81,10 @@ x86_64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
/* Start with the function's type, and get the DW_AT_type attribute,
which is the type of the return value. */
-
- Dwarf_Attribute attr_mem;
- Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type,
- &attr_mem);
- if (attr == NULL)
- /* The function has no return value, like a `void' function in C. */
- return 0;
-
- Dwarf_Die die_mem;
- Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = DWARF_TAG_OR_RETURN (typedie);
-
- /* Follow typedefs and qualifiers to get to the actual type. */
- while (tag == DW_TAG_typedef
- || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
- || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
- {
- attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
- typedie = dwarf_formref_die (attr, &die_mem);
- tag = DWARF_TAG_OR_RETURN (typedie);
- }
+ Dwarf_Die die_mem, *typedie = &die_mem;
+ int tag = dwarf_peeled_die_type (functypedie, typedie);
+ if (tag <= 0)
+ return tag;
Dwarf_Word size;
switch (tag)
@@ -112,6 +95,7 @@ x86_64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_subrange_type:
if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
{
+ Dwarf_Attribute attr_mem, *attr;
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
tag = DWARF_TAG_OR_RETURN (typedie);
@@ -122,16 +106,21 @@ x86_64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
case DW_TAG_enumeration_type:
case DW_TAG_pointer_type:
case DW_TAG_ptr_to_member_type:
- if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
- &attr_mem), &size) != 0)
- {
- if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
- size = 8;
- else
- return -1;
- }
+ {
+ Dwarf_Attribute attr_mem;
+ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+ &attr_mem), &size) != 0)
+ {
+ if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+ size = 8;
+ else
+ return -1;
+ }
+ }
+
if (tag == DW_TAG_base_type)
{
+ Dwarf_Attribute attr_mem;
Dwarf_Word encoding;
if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
&attr_mem),
--
1.7.6.5
9 years, 5 months
[PATCH] tests/backtrace.c (frame_callback): Error on seeing more than 16 frames.
by Mark Wielaard
Don't fill up the test logs with obviously bogus frames.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
tests/ChangeLog | 4 ++++
tests/backtrace.c | 7 +++++++
2 files changed, 11 insertions(+)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index cd8a8e7..5fa8b15 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,7 @@
+2014-06-15 Mark Wielaard <mjw(a)redhat.com>
+
+ * backtrace.c (frame_callback): Error on seeing more than 16 frames.
+
2014-06-11 Mark Wielaard <mjw(a)redhat.com>
* backtrace.c (main): Check that Dwfl was attached by calling
diff --git a/tests/backtrace.c b/tests/backtrace.c
index ce0bd17..aae344c 100644
--- a/tests/backtrace.c
+++ b/tests/backtrace.c
@@ -147,6 +147,13 @@ frame_callback (Dwfl_Frame *state, void *frame_arg)
int *framenop = frame_arg;
Dwarf_Addr pc;
bool isactivation;
+
+ if (*framenop > 16)
+ {
+ error (0, 0, "Too many frames: %d\n", *framenop);
+ return DWARF_CB_ABORT;
+ }
+
if (! dwfl_frame_pc (state, &pc, &isactivation))
{
error (0, 0, "%s", dwfl_errmsg (-1));
--
1.9.3
9 years, 5 months
[PATCH] libebl: Add sym_func_value hook.
by Mark Wielaard
The ARM EABI says that the zero bit of function symbol st_value indicates
whether the symbol points to a THUMB or ARM function. Add a new ebl hook
to adjust the st_value in such a case so that we get the actual value that
the symbol points to. It isn't easily possible to reuse the existing
resolve_sym_value for this purpose, so we end up with another hook that
can be used from dwfl_module_getsym and elflint.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
backends/ChangeLog | 5 +++++
backends/arm_init.c | 1 +
backends/arm_symbol.c | 8 ++++++++
libdwfl/ChangeLog | 4 ++++
libdwfl/dwfl_module_getsym.c | 4 ++--
libebl/ChangeLog | 7 +++++++
libebl/Makefile.am | 3 ++-
libebl/ebl-hooks.h | 5 ++++-
libebl/eblsymfuncval.c | 43 +++++++++++++++++++++++++++++++++++++++++++
libebl/libebl.h | 13 ++++++++++++-
src/ChangeLog | 4 ++++
src/elflint.c | 20 +++++++++++++-------
12 files changed, 105 insertions(+), 12 deletions(-)
create mode 100644 libebl/eblsymfuncval.c
diff --git a/backends/ChangeLog b/backends/ChangeLog
index bc5b843..64b669e 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,8 @@
+2014-06-14 Mark Wielaard <mjw(a)redhat.com>
+
+ * arm_init.c (arm_init): Hook sym_func_value.
+ * arm_symbol.c (arm_sym_func_value): New function.
+
2014-05-19 Mark Wielaard <mjw(a)redhat.com>
* arm_init.c (arm_init): Hook check_reloc_target_type.
diff --git a/backends/arm_init.c b/backends/arm_init.c
index 92e6cd5..e2e20e4 100644
--- a/backends/arm_init.c
+++ b/backends/arm_init.c
@@ -64,6 +64,7 @@ arm_init (elf, machine, eh, ehlen)
HOOK (eh, return_value_location);
HOOK (eh, abi_cfi);
HOOK (eh, check_reloc_target_type);
+ HOOK (eh, sym_func_value);
/* We only unwind the core integer registers. */
eh->frame_nregs = 16;
diff --git a/backends/arm_symbol.c b/backends/arm_symbol.c
index cd467ff..49fca55 100644
--- a/backends/arm_symbol.c
+++ b/backends/arm_symbol.c
@@ -129,3 +129,11 @@ arm_check_reloc_target_type (Ebl *ebl __attribute__ ((unused)), Elf64_Word sh_ty
{
return sh_type == SHT_ARM_EXIDX;
}
+
+/* ARM EABI says that the low bit indicates whether the function
+ symbol value is a THUMB function or not. Mask it off. */
+GElf_Addr
+arm_sym_func_value (Ebl *ebl __attribute__ ((unused)), GElf_Addr val)
+{
+ return val & ~(GElf_Addr)1;
+}
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index ac92a21..888b400 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,7 @@
+2014-06-14 Mark Wielaard <mjw(a)redhat.com>
+
+ * dwfl_module_getsym.c (__libdwfl_getsym): Call ebl_sym_func_value.
+
2014-06-11 Mark Wielaard <mjw(a)redhat.com>
* dwfl_frame.c (__libdwfl_process_free): Reset dwfl->attacherr.
diff --git a/libdwfl/dwfl_module_getsym.c b/libdwfl/dwfl_module_getsym.c
index 917d062..fb192d7 100644
--- a/libdwfl/dwfl_module_getsym.c
+++ b/libdwfl/dwfl_module_getsym.c
@@ -1,5 +1,5 @@
/* Find debugging and symbol information for a module in libdwfl.
- Copyright (C) 2006-2013 Red Hat, Inc.
+ Copyright (C) 2006-2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -119,7 +119,7 @@ __libdwfl_getsym (Dwfl_Module *mod, int ndx, GElf_Sym *sym, GElf_Addr *addr,
descriptors). */
char *ident;
- GElf_Addr st_value = sym->st_value;
+ GElf_Addr st_value = ebl_sym_func_value (mod->ebl, sym->st_value);
*resolved = false;
if (! adjust_st_value && mod->e_type != ET_REL && alloc
&& (GELF_ST_TYPE (sym->st_info) == STT_FUNC
diff --git a/libebl/ChangeLog b/libebl/ChangeLog
index 7198d5e..1c7a2ba 100644
--- a/libebl/ChangeLog
+++ b/libebl/ChangeLog
@@ -1,3 +1,10 @@
+2014-06-14 Mark Wielaard <mjw(a)redhat.com>
+
+ * Makefile.am (gen_SOURCES): Add eblsymfuncval.c.
+ * ebl-hooks.h (sym_func_value): New hook.
+ * eblsymfuncval.c: New file.
+ * libebl.h (sym_func_value): New hook.
+
2014-05-19 Mark Wielaard <mjw(a)redhat.com>
* Makefile.am (gen_SOURCES): Add eblcheckreloctargettype.c.
diff --git a/libebl/Makefile.am b/libebl/Makefile.am
index ec4477b..889c21b 100644
--- a/libebl/Makefile.am
+++ b/libebl/Makefile.am
@@ -55,7 +55,8 @@ gen_SOURCES = eblopenbackend.c eblclosebackend.c eblstrtab.c \
eblsysvhashentrysize.c eblauxvinfo.c eblcheckobjattr.c \
ebl_check_special_section.c ebl_syscall_abi.c eblabicfi.c \
eblstother.c eblinitreg.c ebldwarftoregno.c eblnormalizepc.c \
- eblunwind.c eblresolvesym.c eblcheckreloctargettype.c
+ eblunwind.c eblresolvesym.c eblcheckreloctargettype.c \
+ eblsymfuncval.c
libebl_a_SOURCES = $(gen_SOURCES)
diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h
index 65c62ec..160a821 100644
--- a/libebl/ebl-hooks.h
+++ b/libebl/ebl-hooks.h
@@ -187,9 +187,12 @@ bool EBLHOOK(unwind) (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc,
bool *signal_framep);
/* Returns true if the value can be resolved to an address in an
- allocated section, which will be returned in *SHNDXP.
+ allocated section, which will be returned in *ADDR.
(e.g. function descriptor resolving) */
bool EBLHOOK(resolve_sym_value) (Ebl *ebl, GElf_Addr *addr);
+/* Returns the real value of a symbol function address or offset. */
+GElf_Addr EBLHOOK(sym_func_value) (Ebl *ebl, GElf_Addr val);
+
/* Destructor for ELF backend handle. */
void EBLHOOK(destr) (struct ebl *);
diff --git a/libebl/eblsymfuncval.c b/libebl/eblsymfuncval.c
new file mode 100644
index 0000000..c0b322f
--- /dev/null
+++ b/libebl/eblsymfuncval.c
@@ -0,0 +1,43 @@
+/* Turn a symbol function value into a real function address or offset.
+ Copyright (C) 2014 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 <libeblP.h>
+#include <assert.h>
+
+GElf_Addr
+ebl_sym_func_value (Ebl *ebl, GElf_Addr val)
+{
+ if (ebl == NULL || ebl->sym_func_value == NULL)
+ return val;
+
+ return ebl->sym_func_value (ebl, val);
+}
diff --git a/libebl/libebl.h b/libebl/libebl.h
index d05751f..bc1f491 100644
--- a/libebl/libebl.h
+++ b/libebl/libebl.h
@@ -1,5 +1,5 @@
/* Interface for libebl.
- Copyright (C) 2000-2010, 2013 Red Hat, Inc.
+ Copyright (C) 2000-2010, 2013, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -448,6 +448,17 @@ extern bool ebl_unwind (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc,
extern bool ebl_resolve_sym_value (Ebl *ebl, GElf_Addr *addr)
__nonnull_attribute__ (2);
+/* Returns the real value of a symbol function address or offset
+ (e.g. when the st_value contains some flag bits that need to be
+ masked off). This is different from ebl_resolve_sym_value which
+ only works for actual symbol addresses (in non-ET_REL files) that
+ might resolve to an address in a different section.
+ ebl_sym_func_value is called to turn the given value into the a
+ real address or offset (the original value might not be a real
+ address). This works for both ET_REL when the value is a section
+ offset or ET_EXEC or ET_DYN symbol values, which are addresses. */
+extern GElf_Addr ebl_sym_func_value (Ebl *ebl, GElf_Addr val);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/ChangeLog b/src/ChangeLog
index 7e68036..75341a3 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,7 @@
+2014-06-14 Mark Wielaard <mjw(a)redhat.com>
+
+ * elflint (check_symtab): Check againt ebl_sym_func_value st_value.
+
2014-05-27 Mark Wielaard <mjw(a)redhat.com>
* readelf.c (print_debug): Skip section if name is NULL.
diff --git a/src/elflint.c b/src/elflint.c
index bf6d044..1334ec0 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -768,12 +768,18 @@ section [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n"),
{
GElf_Addr sh_addr = (ehdr->e_type == ET_REL ? 0
: destshdr->sh_addr);
+ GElf_Addr st_value;
+ if (GELF_ST_TYPE (sym->st_info) == STT_FUNC
+ || (GELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC))
+ st_value = ebl_sym_func_value (ebl, sym->st_value);
+ else
+ st_value = sym->st_value;
if (GELF_ST_TYPE (sym->st_info) != STT_TLS)
{
if (! ebl_check_special_symbol (ebl, ehdr, sym, name,
destshdr))
{
- if (sym->st_value - sh_addr > destshdr->sh_size)
+ if (st_value - sh_addr > destshdr->sh_size)
{
/* GNU ld has severe bugs. When it decides to remove
empty sections it leaves symbols referencing them
@@ -798,7 +804,7 @@ section [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n"),
section [%2d] '%s': symbol %zu: st_value out of bounds\n"),
idx, section_name (ebl, idx), cnt);
}
- else if ((sym->st_value - sh_addr
+ else if ((st_value - sh_addr
+ sym->st_size) > destshdr->sh_size)
ERROR (gettext ("\
section [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
@@ -818,12 +824,12 @@ section [%2d] '%s': symbol %zu: referenced section [%2d] '%s' does not have SHF_
{
/* For object files the symbol value must fall
into the section. */
- if (sym->st_value > destshdr->sh_size)
+ if (st_value > destshdr->sh_size)
ERROR (gettext ("\
section [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"),
idx, section_name (ebl, idx), cnt,
(int) xndx, section_name (ebl, xndx));
- else if (sym->st_value + sym->st_size
+ else if (st_value + sym->st_size
> destshdr->sh_size)
ERROR (gettext ("\
section [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
@@ -852,20 +858,20 @@ section [%2d] '%s': symbol %zu: TLS symbol but no TLS program header entry\n"),
}
else
{
- if (sym->st_value
+ if (st_value
< destshdr->sh_offset - phdr->p_offset)
ERROR (gettext ("\
section [%2d] '%s': symbol %zu: st_value short of referenced section [%2d] '%s'\n"),
idx, section_name (ebl, idx), cnt,
(int) xndx, section_name (ebl, xndx));
- else if (sym->st_value
+ else if (st_value
> (destshdr->sh_offset - phdr->p_offset
+ destshdr->sh_size))
ERROR (gettext ("\
section [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"),
idx, section_name (ebl, idx), cnt,
(int) xndx, section_name (ebl, xndx));
- else if (sym->st_value + sym->st_size
+ else if (st_value + sym->st_size
> (destshdr->sh_offset - phdr->p_offset
+ destshdr->sh_size))
ERROR (gettext ("\
--
1.9.3
9 years, 5 months
[PATCH] tests: backtrace.c accept __libc_do_syscall as first frame symname.
by Mark Wielaard
On some architectures (Debian armhl) system calls go through
__libc_do_syscall instead of __kernel_vsyscall. Accept either of
these symbol names for the first backtrace frame.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
tests/ChangeLog | 5 +++++
tests/backtrace.c | 3 ++-
2 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 7c46428..90a2a0e 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,5 +1,10 @@
2014-06-13 Mark Wielaard <mjw(a)redhat.com>
+ * backtrace.c (callback_verify): Accept "__libc_do_syscall" as first
+ frame symname.
+
+2014-06-13 Mark Wielaard <mjw(a)redhat.com>
+
* backtrace-subr.sh (check_native_unsupported): New function.
(check_native): Call it.
(check_native_core): Likewise.
diff --git a/tests/backtrace.c b/tests/backtrace.c
index ce0bd17..1d3948e 100644
--- a/tests/backtrace.c
+++ b/tests/backtrace.c
@@ -98,7 +98,8 @@ callback_verify (pid_t tid, unsigned frameno, Dwarf_Addr pc,
{
case 0:
if (! reduce_frameno && symname
- && strcmp (symname, "__kernel_vsyscall") == 0)
+ && (strcmp (symname, "__kernel_vsyscall") == 0
+ || strcmp (symname, "__libc_do_syscall") == 0))
reduce_frameno = true;
else
assert (symname && strcmp (symname, "raise") == 0);
--
1.7.1
9 years, 5 months
[PATCH] tests: backtrace-subr.sh add check_native_unsupported.
by Mark Wielaard
The special arm check in check_unsupported should only trigger for native
tests, otherwise on arm various backtrace tests would be skipped that
should work just fine.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
tests/ChangeLog | 7 +++++++
tests/backtrace-subr.sh | 13 ++++++++++---
tests/run-backtrace-dwarf.sh | 2 +-
3 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index cd8a8e7..7c46428 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,10 @@
+2014-06-13 Mark Wielaard <mjw(a)redhat.com>
+
+ * backtrace-subr.sh (check_native_unsupported): New function.
+ (check_native): Call it.
+ (check_native_core): Likewise.
+ * run-backtrace-dwarf.sh: Likewise.
+
2014-06-11 Mark Wielaard <mjw(a)redhat.com>
* backtrace.c (main): Check that Dwfl was attached by calling
diff --git a/tests/backtrace-subr.sh b/tests/backtrace-subr.sh
index 875e0b6..1d3d6d4 100644
--- a/tests/backtrace-subr.sh
+++ b/tests/backtrace-subr.sh
@@ -74,13 +74,20 @@ check_unsupported()
echo >&2 $testname: arch not supported
exit 77
fi
+}
+
+check_native_unsupported()
+{
+ err=$1
+ testname=$2
+ check_unsupported $err $testname
# ARM is special. It is supported, but it doesn't use .eh_frame by default
# making the native tests fail unless debuginfo (for glibc) is installed
# and we can fall back on .debug_frame for the CFI.
case "`uname -m`" in
arm* )
- if grep 'dwfl_thread_getframes: No DWARF information found' $1; then
+ if grep 'dwfl_thread_getframes: No DWARF information found' $err; then
echo >&2 $testname: arm needs debuginfo installed for all libraries
exit 77
fi
@@ -109,7 +116,7 @@ check_native()
tempfiles $child.{bt,err}
(set +ex; testrun ${abs_builddir}/backtrace --backtrace-exec=${abs_builddir}/$child 1>$child.bt 2>$child.err; true)
cat $child.{bt,err}
- check_unsupported $child.err $child
+ check_native_unsupported $child.err $child
check_all $child.{bt,err} $child
}
@@ -140,6 +147,6 @@ check_native_core()
tempfiles $core{,.{bt,err}}
(set +ex; testrun ${abs_builddir}/backtrace -e ${abs_builddir}/$child --core=$core 1>$core.bt 2>$core.err; true)
cat $core.{bt,err}
- check_unsupported $core.err $child-$core
+ check_native_unsupported $core.err $child-$core
check_all $core.{bt,err} $child-$core
}
diff --git a/tests/run-backtrace-dwarf.sh b/tests/run-backtrace-dwarf.sh
index a133b32..8834048 100755
--- a/tests/run-backtrace-dwarf.sh
+++ b/tests/run-backtrace-dwarf.sh
@@ -26,5 +26,5 @@ unset VALGRIND_CMD
tempfiles dwarf.{bt,err}
(set +ex; testrun ${abs_builddir}/backtrace-dwarf 1>dwarf.bt 2>dwarf.err; true)
cat dwarf.{bt,err}
-check_unsupported dwarf.err dwarf
+check_native_unsupported dwarf.err dwarf
check_main dwarf.bt dwarf
--
1.7.1
9 years, 5 months