- Fix libelf regression.

This commit is contained in:
roland 2009-01-02 05:37:25 +00:00
parent 28fe4de80f
commit 169e650811
2 changed files with 244 additions and 1 deletions

View File

@ -0,0 +1,236 @@
commit ed9d3bc176b3f0318551d9214b1cec4e49197842
Author: Roland McGrath <roland@redhat.com>
Date: Thu Jan 1 21:22:18 2009 -0800
Fill gaps and update bookkeeping between all sections, not only before a dirty one.
---
libelf/ChangeLog | 7 ++
libelf/elf32_updatefile.c | 142 +++++++++++++++++++++++++++------------------
2 files changed, 93 insertions(+), 56 deletions(-)
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 9578f8b..bb487b1 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,10 @@
+2009-01-01 Roland McGrath <roland@redhat.com>
+
+ * elf32_updatefile.c (__elfw2(LIBELFBITS,updatemmap)):
+ Fill gaps and update bookkeeping between all sections,
+ not only before a dirty one.
+ (__elfw2(LIBELFBITS,updatefile)): Likewise.
+
2008-12-11 Roland McGrath <roland@redhat.com>
* elf32_updatefile.c (__elfw2(LIBELFBITS,updatemmap)): Handle
diff --git a/libelf/elf32_updatefile.c b/libelf/elf32_updatefile.c
index e88f4a4..4e170cb 100644
--- a/libelf/elf32_updatefile.c
+++ b/libelf/elf32_updatefile.c
@@ -1,5 +1,5 @@
/* Write changed data structures.
- Copyright (C) 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc.
+ Copyright (C) 2000,2001,2002,2004,2005,2006,2007,2008,2009 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2000.
@@ -127,7 +127,6 @@ internal_function
__elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
{
ElfW2(LIBELFBITS,Ehdr) *ehdr;
- char *last_position;
/* We need the ELF header several times. */
ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
@@ -204,10 +203,11 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
/* From now on we have to keep track of the last position to eventually
fill the gaps with the prescribed fill byte. */
- last_position = ((char *) elf->map_address + elf->start_offset
- + MAX (elf_typesize (LIBELFBITS, ELF_T_EHDR, 1),
- ehdr->e_phoff)
- + elf_typesize (LIBELFBITS, ELF_T_PHDR, ehdr->e_phnum));
+ char *last_position = ((char *) elf->map_address + elf->start_offset
+ + MAX (elf_typesize (LIBELFBITS, ELF_T_EHDR, 1),
+ ehdr->e_phoff)
+ + elf_typesize (LIBELFBITS,
+ ELF_T_PHDR, ehdr->e_phnum));
/* Write all the sections. Well, only those which are modified. */
if (shnum > 0)
@@ -278,6 +278,35 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
}
}
+ /* Prepare to write at START, and then update LAST_POSITION.
+ If LAST_POSITION was before START, fill in the gap. */
+ inline void prepare_position (char *start)
+ {
+ if (start > last_position)
+ {
+ /* This code assumes that the data blocks for
+ a section are ordered by offset. */
+ size_t written = 0;
+
+ if (last_position < shdr_start)
+ {
+ written = MIN (start - last_position,
+ shdr_start - last_position);
+
+ memset (last_position, __libelf_fill_byte, written);
+ }
+
+ if (last_position + written != start && shdr_end < start)
+ memset (shdr_end, __libelf_fill_byte, start - shdr_end);
+ }
+
+ /* Let it go backward if the sections use a bogus layout with
+ overlaps. We'll overwrite the stupid user's section data
+ with the latest one, rather than crashing. */
+
+ last_position = start;
+ }
+
/* Iterate over all the section in the order in which they
appear in the output file. */
for (size_t cnt = 0; cnt < shnum; ++cnt)
@@ -298,38 +327,10 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
assert (dl->data.d.d_size <= (shdr->sh_size
- (GElf_Off) dl->data.d.d_off));
+ prepare_position (scn_start + dl->data.d.d_off);
+
if ((scn->flags | dl->flags | elf->flags) & ELF_F_DIRTY)
{
- if (scn_start + dl->data.d.d_off > last_position)
- {
- /* This code assumes that the data blocks for
- a section are ordered by offset. */
- size_t written = 0;
-
- if (last_position < shdr_start)
- {
- written = MIN (scn_start + dl->data.d.d_off
- - last_position,
- shdr_start - last_position);
-
- memset (last_position, __libelf_fill_byte,
- written);
- }
-
- if (last_position + written
- != scn_start + dl->data.d.d_off
- && shdr_end < scn_start + dl->data.d.d_off)
- memset (shdr_end, __libelf_fill_byte,
- scn_start + dl->data.d.d_off - shdr_end);
- }
-
- /* Let it go backward if the sections use a bogus
- layout with overlaps. We'll overwrite the stupid
- user's section data with the latest one, rather than
- crashing. */
-
- last_position = scn_start + dl->data.d.d_off;
-
if (unlikely (change_bo))
{
#if EV_NUM != 2
@@ -362,9 +363,19 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
dl = dl->next;
}
while (dl != NULL);
- else if (shdr->sh_type != SHT_NOBITS && scn->index != 0)
- /* We have to trust the existing section header information. */
- last_position += shdr->sh_size;
+ else if (shdr->sh_type != SHT_NOBITS && scn->index != 0
+ && shdr->sh_size != 0)
+ {
+ /* We have to trust the existing section header information.
+
+ If there are any contents at all, we must be sure we've
+ filled in any gap before them, even if it turns out we
+ aren't touching the contents after the gap. */
+
+ prepare_position (scn_start);
+
+ last_position += shdr->sh_size;
+ }
scn->flags &= ~ELF_F_DIRTY;
}
@@ -622,31 +633,39 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
off_t scn_start = elf->start_offset + shdr->sh_offset;
Elf_Data_List *dl = &scn->data_list;
+ /* Prepare to write at START, and then update LAST_OFFSET.
+ If LAST_OFFSET was before START, fill in the gap. */
+ inline bool prepare_offset (off_t start)
+ {
+ if (start > last_offset)
+ {
+ if (unlikely (fill (elf->fildes, last_offset,
+ start - last_offset, fillbuf,
+ &filled) != 0))
+ return true;
+ }
+
+ /* Let it go backward if the sections use a bogus layout with
+ overlaps. We'll overwrite the stupid user's section data
+ with the latest one, rather than crashing. */
+
+ last_offset = start;
+
+ return false;
+ }
+
if (shdr->sh_type != SHT_NOBITS && scn->data_list_rear != NULL
&& scn->index != 0)
do
{
+ if (unlikely (prepare_offset (scn_start + dl->data.d.d_off)))
+ return 1;
+
if ((scn->flags | dl->flags | elf->flags) & ELF_F_DIRTY)
{
char tmpbuf[MAX_TMPBUF];
void *buf = dl->data.d.d_buf;
- if (scn_start + dl->data.d.d_off > last_offset)
- {
- if (unlikely (fill (elf->fildes, last_offset,
- (scn_start + dl->data.d.d_off)
- - last_offset, fillbuf,
- &filled) != 0))
- return 1;
- }
-
- /* Let it go backward if the sections use a bogus
- layout with overlaps. We'll overwrite the stupid
- user's section data with the latest one, rather than
- crashing. */
-
- last_offset = scn_start + dl->data.d.d_off;
-
if (unlikely (change_bo))
{
#if EV_NUM != 2
@@ -696,7 +715,18 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
}
while (dl != NULL);
else if (shdr->sh_type != SHT_NOBITS && scn->index != 0)
- last_offset = scn_start + shdr->sh_size;
+ {
+ /* We have to trust the existing section header information.
+
+ If there are any contents at all, we must be sure we've
+ filled in any gap before them, even if it turns out we
+ aren't touching the contents after the gap. */
+
+ if (shdr->sh_size != 0 && unlikely (prepare_offset (scn_start)))
+ return 1;
+
+ last_offset = scn_start + shdr->sh_size;
+ }
/* Collect the section header table information. */
if (unlikely (change_bo))

View File

@ -1,5 +1,5 @@
%define eu_version 0.138
%define eu_release 1
%define eu_release 2
%if %{?_with_compat:1}%{!?_with_compat:0}
%define compat 1
@ -38,6 +38,8 @@ Patch2: elfutils-robustify.patch
Requires: elfutils-libelf-%{_arch} = %{version}-%{release}
Requires: elfutils-libs-%{_arch} = %{version}-%{release}
Patch3: elfutils-0.138-libelf-padding-fix.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: bison >= 1.875
BuildRequires: flex >= 2.5.4a
@ -156,6 +158,8 @@ find . \( -name configure -o -name config.h.in \) -print | xargs touch
%patch2 -p1 -b .robustify
%patch3 -p1 -b .fixes
find . -name \*.sh ! -perm -0100 -print | xargs chmod +x
%build
@ -263,6 +267,9 @@ rm -rf ${RPM_BUILD_ROOT}
%{_libdir}/libelf.a
%changelog
* Thu Jan 1 2009 Roland McGrath <roland@redhat.com> - 0.138-2
- Fix libelf regression.
* Wed Dec 31 2008 Roland McGrath <roland@redhat.com> - 0.138-1
- Update to 0.138
- Install <elfutils/version.h> header file for applications to use in