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 received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2169676
Title:
libelf elf_update(ELF_C_WRITE) with ELF_F_LAYOUT corrupts section
headers when the section header table is not at the end of the file
(patchelf output); breaks debugedit
To manage notifications about this bug go to:
https://bugs.launchpad.net/elfutils/+bug/2169676/+subscriptions
--
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs