summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS6
-rw-r--r--config/elfutils.spec.in6
-rw-r--r--configure.ac4
-rw-r--r--libdw/ChangeLog21
-rw-r--r--libdw/cfi.c47
-rw-r--r--libdw/cfi.h9
-rw-r--r--libdw/dwarf_frame_cfa.c7
-rw-r--r--libdw/dwarf_frame_register.c4
-rw-r--r--libdw/dwarf_getlocation.c21
-rw-r--r--libdw/libdwP.h4
-rw-r--r--libdwfl/ChangeLog6
-rw-r--r--libdwfl/relocate.c11
-rw-r--r--po/de.po2
-rw-r--r--po/es.po2
-rw-r--r--po/ja.po2
-rw-r--r--po/pl.po2
-rw-r--r--po/uk.po2
-rw-r--r--tests/ChangeLog5
-rw-r--r--tests/addrcfi.c4
19 files changed, 123 insertions, 42 deletions
diff --git a/NEWS b/NEWS
index 95f72a35..d1daab62 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,9 @@
+Version 0.147:
+
+libdw: Fixes in CFI handling, best possible handling of bogus CFA ops.
+
+libdwfl: Ignore R_*_NONE relocs, works around old (binutils) ld -r bugs.
+
Version 0.146:
libdwfl: New function dwfl_core_file_report.
diff --git a/config/elfutils.spec.in b/config/elfutils.spec.in
index 9dab9906..102d723f 100644
--- a/config/elfutils.spec.in
+++ b/config/elfutils.spec.in
@@ -183,6 +183,12 @@ rm -rf ${RPM_BUILD_ROOT}
%{_libdir}/libelf.a
%changelog
+* Mon May 3 2010 Ulrich Drepper <drepper@redhat.com> 0.147-1
+- libdw: Fixes in CFI handling, best possible handling of bogus CFA
+ ops.
+- libdwfl: Ignore R_*_NONE relocs, works around old (binutils) ld -r
+ bugs.
+
* Wed Apr 21 2010 <drepper@redhat.com> 0.146-1
- libdwfl: New function dwfl_core_file_report.
diff --git a/configure.ac b/configure.ac
index 80087873..53cd8c05 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
dnl Process this file with autoconf to produce a configure script.
dnl Configure input file for elfutils. -*-autoconf-*-
dnl
-dnl Copyright (C) 1996-2009, 2010 Red Hat, Inc.
+dnl Copyright (C) 1996-2010 Red Hat, Inc.
dnl
dnl This program is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@ dnl You should have received a copy of the GNU General Public License
dnl along with this program; if not, write to the Free Software Foundation,
dnl Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
dnl
-AC_INIT([Red Hat elfutils],[0.146],[http://bugzilla.redhat.com/bugzilla/],[elfutils])
+AC_INIT([Red Hat elfutils],[0.147],[http://bugzilla.redhat.com/bugzilla/],[elfutils])
AC_CONFIG_AUX_DIR([config])
AC_CONFIG_FILES([config/Makefile])
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index bda46082..c16e91d5 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,24 @@
+2010-04-26 Roland McGrath <roland@redhat.com>
+
+ * cfi.h (struct Dwarf_Frame_s): Add cfa_invalid alternative in cfa_rule.
+ * cfi.c (execute_cfi): Set that instead of doing cfi_assert for
+ DW_CFA_def_cfa_{offset*,register} when a non-offset rule is in force.
+ * dwarf_frame_cfa.c (dwarf_frame_cfa): Handle cfa_invalid.
+
+ * dwarf_getlocation.c (__libdw_intern_expression): Take new arg CFAP.
+ Prepend DW_OP_call_frame_cfa if true.
+ (getlocation): Update caller.
+ * dwarf_frame_cfa.c (dwarf_frame_cfa): Likewise.
+ * dwarf_frame_register.c (dwarf_frame_register): Likewise.
+ * libdwP.h: Update decl.
+
+2010-04-22 Roland McGrath <roland@redhat.com>
+
+ * cfi.c (execute_cfi): Never return without cleanup.
+ Free FS on failure.
+ (cie_cache_initial_state): Adjust caller to expect that free.
+ (__libdw_frame_at_address): Likewise.
+
2010-03-10 Roland McGrath <roland@redhat.com>
* libdw.map (ELFUTILS_0.146): New set. Add dwfl_core_file_report.
diff --git a/libdw/cfi.c b/libdw/cfi.c
index ac197833..3cb378b6 100644
--- a/libdw/cfi.c
+++ b/libdw/cfi.c
@@ -1,5 +1,5 @@
/* CFI program execution.
- Copyright (C) 2009 Red Hat, Inc.
+ Copyright (C) 2009-2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -76,7 +76,8 @@ duplicate_frame_state (const Dwarf_Frame *original,
return copy;
}
-/* Returns a DWARF_E_* error code, usually NOERROR or INVALID_CFI. */
+/* Returns a DWARF_E_* error code, usually NOERROR or INVALID_CFI.
+ Frees *STATE on failure. */
static int
execute_cfi (Dwarf_CFI *cache,
const struct dwarf_cie *cie,
@@ -116,6 +117,12 @@ execute_cfi (Dwarf_CFI *cache,
return true;
}
+ inline void require_cfa_offset (void)
+ {
+ if (unlikely (fs->cfa_rule != cfa_offset))
+ fs->cfa_rule = cfa_invalid;
+ }
+
#define register_rule(regno, r_rule, r_value) do { \
if (unlikely (! enough_registers (regno))) \
goto out; \
@@ -152,10 +159,11 @@ execute_cfi (Dwarf_CFI *cache,
goto advance_loc;
case DW_CFA_set_loc:
- if (unlikely (read_encoded_value (cache, cie->fde_encoding, &program,
- &loc)))
- return INTUSE(dwarf_errno) ();
- break;
+ if (likely (!read_encoded_value (cache, cie->fde_encoding,
+ &program, &loc)))
+ break;
+ result = INTUSE(dwarf_errno) ();
+ goto out;
/* Now all following cases affect this row, but do not touch LOC.
These cases end with 'continue'. We only get out of the
@@ -175,7 +183,7 @@ execute_cfi (Dwarf_CFI *cache,
case DW_CFA_def_cfa_register:
get_uleb128 (regno, program);
- cfi_assert (fs->cfa_rule == cfa_offset);
+ require_cfa_offset ();
fs->cfa_val_reg = regno;
continue;
@@ -188,7 +196,7 @@ execute_cfi (Dwarf_CFI *cache,
case DW_CFA_def_cfa_offset:
get_uleb128 (offset, program);
def_cfa_offset:
- cfi_assert (fs->cfa_rule == cfa_offset);
+ require_cfa_offset ();
fs->cfa_val_offset = offset;
continue;
@@ -323,8 +331,8 @@ execute_cfi (Dwarf_CFI *cache,
cfi_assert (prev != NULL);
free (fs);
fs = prev;
+ continue;
}
- continue;
case DW_CFA_nop:
continue;
@@ -395,8 +403,10 @@ execute_cfi (Dwarf_CFI *cache,
free (prev);
}
- if (result == DWARF_E_NOERROR)
+ if (likely (result == DWARF_E_NOERROR))
*state = fs;
+ else
+ free (fs);
return result;
}
@@ -458,17 +468,14 @@ cie_cache_initial_state (Dwarf_CFI *cache, struct dwarf_cie *cie)
cie->initial_instructions_end, false,
0, (Dwarf_Addr) -1l);
- if (unlikely (result != DWARF_E_NOERROR))
+ if (likely (result == DWARF_E_NOERROR))
{
- free (cie_fs);
- return result;
+ /* Now we have the initial state of things that all
+ FDEs using this CIE will start from. */
+ cie_fs->cache = cache;
+ cie->initial_state = cie_fs;
}
- /* Now we have the initial state of things that all
- FDEs using this CIE will start from. */
- cie_fs->cache = cache;
- cie->initial_state = cie_fs;
-
return result;
}
@@ -491,9 +498,7 @@ __libdw_frame_at_address (Dwarf_CFI *cache, struct dwarf_fde *fde,
result = execute_cfi (cache, fde->cie, &fs,
fde->instructions, fde->instructions_end, false,
fde->start, address);
- if (unlikely (result != DWARF_E_NOERROR))
- free (fs);
- else
+ if (likely (result == DWARF_E_NOERROR))
*frame = fs;
}
return result;
diff --git a/libdw/cfi.h b/libdw/cfi.h
index 64f3f157..e04e76dd 100644
--- a/libdw/cfi.h
+++ b/libdw/cfi.h
@@ -1,5 +1,5 @@
/* Internal definitions for libdw CFI interpreter.
- Copyright (C) 2009 Red Hat, Inc.
+ Copyright (C) 2009-2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -191,8 +191,11 @@ struct Dwarf_Frame_s
which has the return_address_register and signal_frame flag. */
struct dwarf_fde *fde;
- /* The CFA is unknown, is R+N, or is computed by a DWARF expression. */
- enum { cfa_undefined, cfa_offset, cfa_expr } cfa_rule;
+ /* The CFA is unknown, is R+N, or is computed by a DWARF expression.
+ A bogon in the CFI can indicate an invalid/incalculable rule.
+ We store that as cfa_invalid rather than barfing when processing it,
+ so callers can ignore the bogon unless they really need that CFA. */
+ enum { cfa_undefined, cfa_offset, cfa_expr, cfa_invalid } cfa_rule;
union
{
Dwarf_Op offset;
diff --git a/libdw/dwarf_frame_cfa.c b/libdw/dwarf_frame_cfa.c
index d1c57108..0ba26b2f 100644
--- a/libdw/dwarf_frame_cfa.c
+++ b/libdw/dwarf_frame_cfa.c
@@ -84,10 +84,15 @@ dwarf_frame_cfa (fs, ops, nops)
result = __libdw_intern_expression
(NULL, fs->cache->other_byte_order,
fs->cache->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8,
- &fs->cache->expr_tree, &fs->cfa_data.expr, false,
+ &fs->cache->expr_tree, &fs->cfa_data.expr, false, false,
ops, nops, IDX_debug_frame);
break;
+ case cfa_invalid:
+ __libdw_seterrno (DWARF_E_INVALID_CFI);
+ result = -1;
+ break;
+
default:
abort ();
}
diff --git a/libdw/dwarf_frame_register.c b/libdw/dwarf_frame_register.c
index 3d232e95..e42b76bf 100644
--- a/libdw/dwarf_frame_register.c
+++ b/libdw/dwarf_frame_register.c
@@ -1,5 +1,5 @@
/* Get register location expression for frame.
- Copyright (C) 2009 Red Hat, Inc.
+ Copyright (C) 2009-2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -131,7 +131,7 @@ dwarf_frame_register (fs, regno, ops_mem, ops, nops)
fs->cache->other_byte_order,
address_size,
&fs->cache->expr_tree, &block,
- reg->rule == reg_val_expression,
+ true, reg->rule == reg_val_expression,
ops, nops, IDX_debug_frame) < 0)
return -1;
break;
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c
index 720b20f4..f362fe22 100644
--- a/libdw/dwarf_getlocation.c
+++ b/libdw/dwarf_getlocation.c
@@ -1,5 +1,5 @@
/* Return location expression list.
- Copyright (C) 2000-2009 Red Hat, Inc.
+ Copyright (C) 2000-2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2000.
@@ -221,7 +221,8 @@ int
internal_function
__libdw_intern_expression (Dwarf *dbg,
bool other_byte_order, unsigned int address_size,
- void **cache, const Dwarf_Block *block, bool valuep,
+ void **cache, const Dwarf_Block *block,
+ bool cfap, bool valuep,
Dwarf_Op **llbuf, size_t *listlen, int sec_index)
{
/* Check whether we already looked at this list. */
@@ -444,6 +445,9 @@ __libdw_intern_expression (Dwarf *dbg,
++n;
}
+ if (cfap)
+ ++n;
+
/* Allocate the array. */
Dwarf_Op *result;
if (dbg != NULL)
@@ -463,6 +467,16 @@ __libdw_intern_expression (Dwarf *dbg,
*llbuf = result;
*listlen = n;
+ if (cfap)
+ {
+ /* Synthesize the operation to push the CFA before the expression. */
+ --n;
+ result[0].atom = DW_OP_call_frame_cfa;
+ result[0].number = 0;
+ result[0].number2 = 0;
+ result[0].offset = -1;
+ }
+
do
{
/* We populate the array from the back since the list is backwards. */
@@ -507,7 +521,8 @@ getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
Dwarf_Op **llbuf, size_t *listlen, int sec_index)
{
return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order,
- cu->address_size, &cu->locs, block, false,
+ cu->address_size, &cu->locs, block,
+ false, false,
llbuf, listlen, sec_index);
}
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 99f53680..7a3a360a 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -440,10 +440,10 @@ extern int __libdw_intern_expression (Dwarf *dbg,
bool other_byte_order,
unsigned int address_size,
void **cache, const Dwarf_Block *block,
- bool valuep,
+ bool cfap, bool valuep,
Dwarf_Op **llbuf, size_t *listlen,
int sec_index)
- __nonnull_attribute__ (4, 5, 7, 8) internal_function;
+ __nonnull_attribute__ (4, 5, 8, 9) internal_function;
/* Return error code of last failing function call. This value is kept
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 54ac53fa..a9f36d96 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,9 @@
+2010-04-26 Roland McGrath <roland@redhat.com>
+
+ * relocate.c (relocate_section): Treat R_*_NONE reloc as no reloc.
+ Works around probably-wrong ld -r behavior for case of a DWARF address
+ constant that refers to a discarded SHF_ALLOC section.
+
2010-04-14 Roland McGrath <roland@redhat.com>
* link_map.c (report_r_debug): Limit iterations on the l_next chain to
diff --git a/libdwfl/relocate.c b/libdwfl/relocate.c
index 121a481b..0075c7f9 100644
--- a/libdwfl/relocate.c
+++ b/libdwfl/relocate.c
@@ -1,5 +1,5 @@
/* Relocate debug information.
- Copyright (C) 2005-2009 Red Hat, Inc.
+ Copyright (C) 2005-2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -325,6 +325,15 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
{
/* First see if this is a reloc we can handle.
If we are skipping it, don't bother resolving the symbol. */
+
+ if (unlikely (rtype == 0))
+ /* In some odd situations, the linker can leave R_*_NONE relocs
+ behind. This is probably bogus ld -r behavior, but the only
+ cases it's known to appear in are harmless: DWARF data
+ referring to addresses in a section that has been discarded.
+ So we just pretend it's OK without further relocation. */
+ return DWFL_E_NOERROR;
+
Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype);
if (unlikely (type == ELF_T_NUM))
return DWFL_E_BADRELTYPE;
diff --git a/po/de.po b/po/de.po
index cc0c6630..3796c448 100644
--- a/po/de.po
+++ b/po/de.po
@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: elfutils VERSION\n"
"Report-Msgid-Bugs-To: http://bugzilla.redhat.com/\n"
-"POT-Creation-Date: 2010-04-21 07:41-0700\n"
+"POT-Creation-Date: 2010-05-03 14:14-0700\n"
"PO-Revision-Date: 2009-06-29 15:15+0200\n"
"Last-Translator: Michael Münch <micm@fedoraproject.org>\n"
"Language-Team: German\n"
diff --git a/po/es.po b/po/es.po
index e128250c..63657625 100644
--- a/po/es.po
+++ b/po/es.po
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: elfutils.master.es\n"
"Report-Msgid-Bugs-To: http://bugzilla.redhat.com/\n"
-"POT-Creation-Date: 2010-04-21 07:41-0700\n"
+"POT-Creation-Date: 2010-05-03 14:14-0700\n"
"PO-Revision-Date: 2010-04-19 10:51-0300\n"
"Last-Translator: Héctor Daniel Cabrera <logan@fedoraproject.org>\n"
"Language-Team: Fedora Spanish <trans-es@lists.fedoraproject.org>\n"
diff --git a/po/ja.po b/po/ja.po
index cf928f07..06b8b3f8 100644
--- a/po/ja.po
+++ b/po/ja.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ja\n"
"Report-Msgid-Bugs-To: http://bugzilla.redhat.com/\n"
-"POT-Creation-Date: 2010-04-21 07:41-0700\n"
+"POT-Creation-Date: 2010-05-03 14:14-0700\n"
"PO-Revision-Date: 2009-09-20 15:32+0900\n"
"Last-Translator: Hyu_gabaru Ryu_ichi <hyu_gabaru@yahoo.co.jp>\n"
"Language-Team: Japanese <jp@li.org>\n"
diff --git a/po/pl.po b/po/pl.po
index aaf9a3d1..da37f61b 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: pl\n"
"Report-Msgid-Bugs-To: http://bugzilla.redhat.com/\n"
-"POT-Creation-Date: 2010-04-21 07:41-0700\n"
+"POT-Creation-Date: 2010-05-03 14:14-0700\n"
"PO-Revision-Date: 2007-03-16 20:10+0100\n"
"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
"Language-Team: Polish <trans-pl@lists.fedoraproject.org>\n"
diff --git a/po/uk.po b/po/uk.po
index e7ec2958..9df3811f 100644
--- a/po/uk.po
+++ b/po/uk.po
@@ -5,7 +5,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: http://bugzilla.redhat.com/\n"
-"POT-Creation-Date: 2010-04-21 07:41-0700\n"
+"POT-Creation-Date: 2010-05-03 14:14-0700\n"
"PO-Revision-Date: 2010-04-15 07:24+0300\n"
"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
"Language-Team: Ukrainian <kde-i18n-doc@kde.org>\n"
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 83b4b747..e2fe66f2 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,8 @@
+2010-04-22 Roland McGrath <roland@redhat.com>
+
+ * addrcfi.c (handle_cfi): Fix function name in error message.
+ Use dwarf_errmsg, not dwfl_errmsg, after dwarf_cfi_addrframe.
+
2010-04-14 Roland McGrath <roland@redhat.com>
* Makefile.am (EXTRA_DIST): Add run-test-flag-nobits.sh here too.
diff --git a/tests/addrcfi.c b/tests/addrcfi.c
index 2a3db05c..4e042418 100644
--- a/tests/addrcfi.c
+++ b/tests/addrcfi.c
@@ -1,5 +1,5 @@
/* Test program for CFI handling.
- Copyright (C) 2009 Red Hat, Inc.
+ Copyright (C) 2009-2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -100,7 +100,7 @@ handle_cfi (Dwfl *dwfl, const char *which, Dwarf_CFI *cfi,
int result = dwarf_cfi_addrframe (cfi, pc - stuff->bias, &stuff->frame);
if (result != 0)
{
- error (0, 0, "dwarf_addrframe (%s): %s", which, dwfl_errmsg (-1));
+ error (0, 0, "dwarf_cfi_addrframe (%s): %s", which, dwarf_errmsg (-1));
return 1;
}