view elf.c @ 2:7bf4a164d5bb default tip

fix bug: long_options have to be zero terminated
author Peter Meerwald <p.meerwald@bct-electronic.com>
date Fri, 20 Jul 2012 11:28:30 +0200
parents bbbfb3f97919
children
line wrap: on
line source


#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include <elf.h>
#if defined(HAVE_SYS_LINK_H)
#  include <sys/link.h> /* Find DT_RPATH on Solaris 2.6 */
#endif /*  HAVE_SYS_LINK_H */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include "protos.h"

int
elf32_open(const char *filename, int flags, Elf32_Ehdr *ehdr)
{
   int fd;

   fd = open(filename, flags);
   if (fd == -1)
   {
     perror ("open");
     return -1;
   }

   if (read(fd, ehdr, sizeof(*ehdr)) != sizeof(*ehdr))
   {
     perror ("reading header");
     close(fd);
     return -1;
   }

   if (0 != memcmp(ehdr->e_ident, ELFMAG, SELFMAG) ||
       ehdr->e_ident[EI_CLASS] != ELFCLASS32 ||
       ehdr->e_ident[EI_DATA] != ELFDATA2 ||
       ehdr->e_ident[EI_VERSION] != EV_CURRENT)
   {
     fprintf(stderr,
#ifdef WORDS_BIGENDIAN
             "`%s' probably isn't a %d-bit MSB-first ELF file.\n",
#else /* not WORD_BIGENDIAN */
             "`%s' probably isn't a %d-bit LSB-first ELF file.\n",
#endif /* not WORD_BIGENDIAN */
             filename, 32);
     close(fd);
     errno = ENOEXEC; /* Hm, is this the best errno code to use? */
     return -1;
   }

   printf("32-bit ELF file\n");

   if (ehdr->e_phentsize != sizeof(Elf32_Phdr))
   {
     fprintf(stderr, "section size was read as %d, not %lu!\n",
            ehdr->e_phentsize, sizeof(Elf32_Phdr));
     close(fd);
     return -1;
   }
   return fd;
}

int
elf64_open(const char *filename, int flags, Elf64_Ehdr *ehdr)
{
   int fd;

   fd = open(filename, flags);
   if (fd == -1)
   {
     perror ("open");
     return -1;
   }

   if (read(fd, ehdr, sizeof(*ehdr)) != sizeof(*ehdr))
   {
     perror ("reading header");
     close(fd);
     return -1;
   }

   if (0 != memcmp(ehdr->e_ident, ELFMAG, SELFMAG) ||
       ehdr->e_ident[EI_CLASS] != ELFCLASS64 ||
       ehdr->e_ident[EI_DATA] != ELFDATA2 ||
       ehdr->e_ident[EI_VERSION] != EV_CURRENT)
   {
     fprintf(stderr,
#ifdef WORDS_BIGENDIAN
             "`%s' probably isn't a %d-bit MSB-first ELF file.\n",
#else /* not WORD_BIGENDIAN */
             "`%s' probably isn't a %d-bit LSB-first ELF file.\n",
#endif /* not WORD_BIGENDIAN */
             filename, 64);
     close(fd);
     errno = ENOEXEC; /* Hm, is this the best errno code to use? */
     return -1;
   }

   printf("64-bit ELF file\n");

   if (ehdr->e_phentsize != sizeof(Elf64_Phdr))
   {
     fprintf(stderr, "section size was read as %d, not %lu!\n",
            ehdr->e_phentsize, sizeof(Elf64_Phdr));
     close(fd);
     return -1;
   }
   return fd;
}

int
elf32_find_dynamic_section(int fd, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr)
{
  int i;
  if (lseek(fd, ehdr->e_phoff, SEEK_SET) == -1)
  {
    perror ("positioning for sections");
    return 1;
  }

  for (i = 0; i < ehdr->e_phnum; i++)
  {
    if (read(fd, phdr, sizeof(*phdr)) != sizeof(*phdr))
    {
      perror ("reading section header");
      return 1;
    }
    if (phdr->p_type == PT_DYNAMIC)
      break;
  }
  if (i == ehdr->e_phnum)
    {
      fprintf (stderr, "No dynamic section found.\n");
      return 2;
    }

  if (0 == phdr->p_filesz)
    {
      fprintf (stderr, "Length of dynamic section is zero.\n");
      return 3;
    }

  return 0;
}

int
elf64_find_dynamic_section(int fd, Elf64_Ehdr *ehdr, Elf64_Phdr *phdr)
{
  int i;
  if (lseek(fd, ehdr->e_phoff, SEEK_SET) == -1)
  {
    perror ("positioning for sections");
    return 1;
  }

  for (i = 0; i < ehdr->e_phnum; i++)
  {
    if (read(fd, phdr, sizeof(*phdr)) != sizeof(*phdr))
    {
      perror ("reading section header");
      return 1;
    }
    if (phdr->p_type == PT_DYNAMIC)
      break;
  }
  if (i == ehdr->e_phnum)
    {
      fprintf (stderr, "No dynamic section found.\n");
      return 2;
    }

  if (0 == phdr->p_filesz)
    {
      fprintf (stderr, "Length of dynamic section is zero.\n");
      return 3;
    }

  return 0;
}

void
elf_close(int fd)
{
  close(fd);
}

const char *
elf_tagname(int tag)
{
  switch (tag) {
  case DT_RPATH:
    return "RPATH";
    break;
#if defined(DT_RUNPATH)
  case DT_RUNPATH:
    return "RUNPATH";
    break;
#endif /* DT_RUNPATH */
  }
  return "UNKNOWN";
}

int
elf_dynpath_tag(int tag)
{
  return ( tag == DT_RPATH
#if defined(DT_RUNPATH)
           || tag == DT_RUNPATH
#endif /* DT_RUNPATH */
           );
}

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.