This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: libelf RDWR and elf_newscn do not work


On Fri, 2013-10-11 at 13:36 +0200, Mark Wielaard wrote:
> On Thu, 2013-10-10 at 17:34 +0200, Jiri Slaby wrote:
> > On 10/10/2013 03:16 PM, Mark Wielaard wrote:
> > > @@ -764,7 +765,8 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
> > >  	    (*shdr_fctp) (&shdr_data[scn->index],
> > >  			  scn->shdr.ELFW(e,LIBELFBITS),
> > >  			  sizeof (ElfW2(LIBELFBITS,Shdr)), 1);
> > > -	  else if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
> > > +	  else if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL
> > > +		   || (elf->flags & ELF_F_DIRTY))
> > 
> > I seem to miss where is elf->flags |= ELF_F_DIRTY in the newscn path...
> > Should it be added too?
> 
> No, I don't think it should be set there. But you do raise a good point.
> I had assumed that since newscn increases e_shnum it would mark the
> whole Elf dirty. But now that I look it doesn't seem to. if e_shnum is
> changed then the ehdr->flags do get ELF_F_DIRTY set (see elf_update ->
> elf32_updatenull). But I cannot immediately see why the whole Elf file
> is marked dirty (although it is in your example).
> 
> So either I am missing something that makes it correct anyway, or the
> check should be against ehdr->flags. I am digging...

So elf_update will first determine the new number of sections from the
list updated by newscn. Then it will call updatenull to determine what
actually changed, including comparing the new shnum with the
ehdr->e_shnum with update_if_changed, which will set the ehdr_flags to
ELF_F_DIRTY. Then ehdr is written and the ehdr_flags dirty bit is
cleared. So we cannot directly use that.

But update_null will also calculate the new ehdr->e_shoff, which will
change is any section is added/removed/changed size, etc. And in that
case it will set the ELF_F_DIRTY bit of the elf->flags. So I do think
the patch is correct.

Cheers,

Mark
>From 5c163114a3ea4ece6fea9fe5f9cded6965f98666 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Tue, 5 Nov 2013 16:27:32 +0100
Subject: [PATCH] libelf: Write all section headers if elf flags contains ELF_F_DIRTY.

When ehdr e_shoff changes, elf flags is set dirty. This indicates that
the section header moved because sections were added/removed or changed
in size.

Reported-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 libelf/ChangeLog          |    5 +++++
 libelf/elf32_updatefile.c |    6 ++++--
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index d9d6421..005f7a4 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,8 @@
+2013-11-05  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_updatefile.c (elfXX_updatefile): Copy all section headers
+	if elf->flags dirty.
+
 2013-10-01  Petr Machata  <pmachata@redhat.com>
 
 	* elf.h: Update from glibc.
diff --git a/libelf/elf32_updatefile.c b/libelf/elf32_updatefile.c
index 296b1ac..c4af9c0 100644
--- a/libelf/elf32_updatefile.c
+++ b/libelf/elf32_updatefile.c
@@ -633,7 +633,8 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
 #endif
 
       ElfW2(LIBELFBITS,Shdr) *shdr_data;
-      if (change_bo || elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
+      if (change_bo || elf->state.ELFW(elf,LIBELFBITS).shdr == NULL
+	  || (elf->flags & ELF_F_DIRTY))
 	shdr_data = (ElfW2(LIBELFBITS,Shdr) *)
 	  alloca (shnum * sizeof (ElfW2(LIBELFBITS,Shdr)));
       else
@@ -764,7 +765,8 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
 	    (*shdr_fctp) (&shdr_data[scn->index],
 			  scn->shdr.ELFW(e,LIBELFBITS),
 			  sizeof (ElfW2(LIBELFBITS,Shdr)), 1);
-	  else if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
+	  else if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL
+		   || (elf->flags & ELF_F_DIRTY))
 	    memcpy (&shdr_data[scn->index], scn->shdr.ELFW(e,LIBELFBITS),
 		    sizeof (ElfW2(LIBELFBITS,Shdr)));
 
-- 
1.7.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]