https://sourceware.org/bugzilla/show_bug.cgi?id=34468

--- Comment #8 from Mark Wielaard <mark at klomp dot org> ---
Sorry it took me so long to look into this.

The main issue is that patchelf puts the section headers in the middle of the
file.
debugedit and libelf (for ELF_C_RDWR, when ELF_F_LAYOUT is given) assume it
will be at the end of the file, after the sections.

As Brandon noticed fill_mmap does take this into account. It checks both
against shdr_start and shdr_end. For elfutils libelf we should have a similar
file_fill.

For debugedit using ELF_C_RDWR_MMAP might work, but it comes with the penalty
of having to mark all sections ELF_F_DIRTY (which might indicate that either
the fill_mmap approach doesn't fully work, or that there is more to do in
debugedit because the SHF_ALLOC and not allocated sections are mixed). Also
ELF_C_RDWR_MMAP might fail on larger files where we have to extend the file
(because we are writing longer strings), remapping may fail when if there is
not sufficient space to expand a  mapping at  its  current  location (libelf
doesn't use MREMAP_MAYMOVE because it doesn't know if or which internal
pointers it might have to update).

So for debugedit I would propose to relayout the sections, and make sure the
shdrs are at the end, by setting need_update if the section headers aren't at
the end.

diff --git a/tools/debugedit.c b/tools/debugedit.c
index 510c0d7b3f29..7d645d1477aa 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -234,7 +234,7 @@ typedef struct
   GElf_Ehdr ehdr;
   Elf_Scn **scn;
   const char *filename;
-  int lastscn;
+  uint64_t end_offset;
   size_t phnum;
   size_t shnum;
   size_t shstrndx;
@@ -3666,6 +3666,7 @@ fdopen_dso (int fd, const char *name)
   int i;
   DSO *dso = NULL;
   size_t phnum, shnum, shstrndx;
+  uint64_t end_offset = 0;

   if (dest_dir == NULL && (!do_build_id || no_recompute_build_id))
     elf = elf_begin (fd, ELF_C_READ, NULL);
@@ -3750,7 +3751,10 @@ fdopen_dso (int fd, const char *name)
     {
       dso->scn[i] = elf_getscn (elf, i);
       gelf_getshdr (dso->scn[i], dso->shdr + i);
+      if (dso->shdr[i].sh_offset + dso->shdr[i].sh_size > end_offset)
+       end_offset = dso->shdr[i].sh_offset + dso->shdr[i].sh_size;
     }
+  dso->end_offset = end_offset;

   dso->filename = (const char *) strdup (name);
   setup_strings (&dso->debug_str);
@@ -4138,6 +4142,15 @@ main (int argc, char *argv[])
                 || (do_build_id && build_id != NULL));
 #endif

+  /* If the shdrs are not at the and there are phdrs then we do need
+     to update the offsets so that the shdrs come last.
+     https://sourceware.org/bugzilla/show_bug.cgi?id=34468  */
+  need_update = (need_update
+                || (dso->phnum != 0
+                    && (dso->ehdr.e_shoff
+                        + gelf_fsize (dso->elf, ELF_T_SHDR, dso->shnum,
+                                      EV_CURRENT)) < dso->end_offset));
+
   /* We might have changed the size of some debug sections. If so make
      sure the section headers are updated and the data offsets are
      correct. We set ELF_F_LAYOUT above because we don't want libelf

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Reply via email to