This is the mail archive of the 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]

elf_cntl(ELF_C_FDREAD) breaks elf64_getshdr() with non-mmap()ed ELF files

I'm seeing a problem with all versions of elfutils from 0.152 up to
latest git head (a problem probably originating in 2007).

The symptoms are that using elf_cntl(..., ELF_C_READ, NULL) to pull a
whole ELF file into memory so you can close it causes assertion failures
inside elf64_getshdr() and gelf_getshdr():

scnwalk: elf32_getshdr.c:95: load_shdr_wrlock: Assertion `ehdr->e_ident[5] != 1 || (! 1 && ((uintptr_t) file_shdr & (__alignof__ (Elf64_Shdr) - 1)) != 0)' failed.

These failures do not occur if you haven't used elf_cntl(), or if you
have used ELF_C_READ_MMAP rather than ELF_C_READ at elf_begin() time.

Testcase below. It looks to me like elf_begin.c:file_read_elf() is
concluding that the ELF file will require increased alignment to use (so
cannot be directly mapped), following which
elf32_getshdr.c:load_shdr_wrlock() concludes that it does *not* require
increased alignment, thus the assertion failure. These are perfectly
normal object files compiled on the same architecture, no byteswapping
needed and one would assume no alignment increase either: indeed you can
see this failure when you try to work over the very object files that
comprise the version of elfutils being tested.

I'll look into this further, but for now here's a testcase, which on
64-bit x86 fails for me with the assertion failure above when run with
e.g. elfutils/libelf/elf64_getshdr.o as a parameter (assuming you've
compiled elfutils so the object file is there, of course).

Removing the call to elf_cntl() (and the close(), obviously) fixes it,
as does changing ELF_C_READ to ELF_C_READ_MMAP.

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <gelf.h>
#include <libelf.h>

int main (int argc, char *argv[])
  int fd;
  Elf *foo;
  Elf_Scn *sp;

  if (argc < 2)
      fprintf (stderr, "syntax: scnwalk filename\n");
      exit (1);

  if (elf_version(EV_CURRENT) == EV_NONE)
      fprintf (stderr, "elf_version failed: %s\n",
               elf_errmsg (elf_errno()));

  if ((fd = open (argv[1], O_RDONLY)) < 0)
      fprintf (stderr, "Cannot open %s: %s\n",
               argv[1], strerror (errno));
      exit (1);

  foo = elf_begin (fd, ELF_C_READ, NULL);
  if (elf_cntl (foo, ELF_C_FDREAD) < 0)
      fprintf (stderr, "Cannot elf_cntl(%p) for %s: %s\n", foo, argv[1],
               elf_errmsg (elf_errno()));
      exit (1);
  close (fd);

  for (sp = NULL; (sp = elf_nextscn (foo, sp)) != NULL;)
      elf64_getshdr (sp); /* boom! */

  elf_end (foo);

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