Blame tests/newdata.c

Packit Service 97d2fb
/* Test program for elf_newdata function.
Packit Service 97d2fb
   Copyright (C) 2015 Red Hat, Inc.
Packit Service 97d2fb
   This file is part of elfutils.
Packit Service 97d2fb
Packit Service 97d2fb
   This file is free software; you can redistribute it and/or modify
Packit Service 97d2fb
   it under the terms of the GNU General Public License as published by
Packit Service 97d2fb
   the Free Software Foundation; either version 3 of the License, or
Packit Service 97d2fb
   (at your option) any later version.
Packit Service 97d2fb
Packit Service 97d2fb
   elfutils is distributed in the hope that it will be useful, but
Packit Service 97d2fb
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 97d2fb
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 97d2fb
   GNU General Public License for more details.
Packit Service 97d2fb
Packit Service 97d2fb
   You should have received a copy of the GNU General Public License
Packit Service 97d2fb
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit Service 97d2fb
Packit Service 97d2fb
#ifdef HAVE_CONFIG_H
Packit Service 97d2fb
# include <config.h>
Packit Service 97d2fb
#endif
Packit Service 97d2fb
Packit Service 97d2fb
#include <errno.h>
Packit Service 97d2fb
#include <fcntl.h>
Packit Service 97d2fb
#include <inttypes.h>
Packit Service 97d2fb
#include <stdio.h>
Packit Service 97d2fb
#include <stdlib.h>
Packit Service 97d2fb
#include <string.h>
Packit Service 97d2fb
#include <unistd.h>
Packit Service 97d2fb
Packit Service 97d2fb
#include ELFUTILS_HEADER(elf)
Packit Service 97d2fb
#include <gelf.h>
Packit Service 97d2fb
Packit Service 97d2fb
// Random data string (16 bytes).
Packit Service 97d2fb
static char *DATA = "123456789ABCDEF";
Packit Service 97d2fb
static size_t DATA_LEN = 16;
Packit Service 97d2fb
Packit Service 97d2fb
static void
Packit Service 97d2fb
add_section_data (Elf *elf, char *buf, size_t len)
Packit Service 97d2fb
{
Packit Service 97d2fb
  printf ("Adding %zd bytes.\n", len);
Packit Service 97d2fb
Packit Service 97d2fb
  Elf_Scn *scn = elf_getscn (elf, 1);
Packit Service 97d2fb
  if (scn == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("couldn't get data section: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  Elf_Data *data = elf_newdata (scn);
Packit Service 97d2fb
  if (data == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("cannot create newdata for section: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  data->d_buf = buf;
Packit Service 97d2fb
  data->d_type = ELF_T_BYTE;
Packit Service 97d2fb
  data->d_size = len;
Packit Service 97d2fb
  data->d_align = 1;
Packit Service 97d2fb
  data->d_version = EV_CURRENT;
Packit Service 97d2fb
Packit Service 97d2fb
  // Let the library compute the internal structure information.
Packit Service 97d2fb
  if (elf_update (elf, ELF_C_NULL) < 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static Elf *
Packit Service 97d2fb
create_elf (int fd, int class, int use_mmap)
Packit Service 97d2fb
{
Packit Service 97d2fb
  Elf *elf = elf_begin (fd, use_mmap ? ELF_C_WRITE_MMAP : ELF_C_WRITE, NULL);
Packit Service 97d2fb
  if (elf == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  // Create an ELF header.
Packit Service 97d2fb
  if (gelf_newehdr (elf, class) == 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  GElf_Ehdr ehdr_mem;
Packit Service 97d2fb
  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
Packit Service 97d2fb
  if (ehdr == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  // Initialize header.
Packit Service 97d2fb
  ehdr->e_ident[EI_DATA] = class == ELFCLASS32 ? ELFDATA2LSB : ELFDATA2MSB;
Packit Service 97d2fb
  ehdr->e_ident[EI_OSABI] = ELFOSABI_GNU;
Packit Service 97d2fb
  ehdr->e_type = ET_NONE;
Packit Service 97d2fb
  ehdr->e_machine = class == ELFCLASS32 ? EM_PPC : EM_X86_64;
Packit Service 97d2fb
  ehdr->e_version = EV_CURRENT;
Packit Service 97d2fb
Packit Service 97d2fb
  // Update the ELF header.
Packit Service 97d2fb
  if (gelf_update_ehdr (elf, ehdr) == 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("cannot update ELF header: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  // Create a section.
Packit Service 97d2fb
  Elf_Scn *scn = elf_newscn (elf);
Packit Service 97d2fb
  if (scn == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("cannot create new section: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  GElf_Shdr shdr_mem;
Packit Service 97d2fb
  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
Packit Service 97d2fb
  if (shdr == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("cannot get header for data section: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  shdr->sh_type = SHT_PROGBITS;
Packit Service 97d2fb
  shdr->sh_flags = 0;
Packit Service 97d2fb
  shdr->sh_addr = 0;
Packit Service 97d2fb
  shdr->sh_link = SHN_UNDEF;
Packit Service 97d2fb
  shdr->sh_info = SHN_UNDEF;
Packit Service 97d2fb
  shdr->sh_addralign = 1;
Packit Service 97d2fb
  shdr->sh_entsize = 1;
Packit Service 97d2fb
  shdr->sh_name = 0;
Packit Service 97d2fb
Packit Service 97d2fb
  // Finish section, update the header.
Packit Service 97d2fb
  if (gelf_update_shdr (scn, shdr) == 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("cannot update header for DATA section: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  // Add some data to the section.
Packit Service 97d2fb
  add_section_data (elf, DATA, DATA_LEN);
Packit Service 97d2fb
Packit Service 97d2fb
  // Write everything to disk.
Packit Service 97d2fb
  if (elf_update (elf, ELF_C_WRITE) < 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  return elf;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static Elf *
Packit Service 97d2fb
read_elf (int fd, int use_mmap)
Packit Service 97d2fb
{
Packit Service 97d2fb
  printf ("Reading ELF file\n");
Packit Service 97d2fb
  Elf *elf = elf_begin (fd, use_mmap ? ELF_C_RDWR_MMAP : ELF_C_RDWR, NULL);
Packit Service 97d2fb
  if (elf == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("cannot create ELF descriptor read-again: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  return elf;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static void
Packit Service 97d2fb
check_section_size (Elf *elf, size_t size)
Packit Service 97d2fb
{
Packit Service 97d2fb
  Elf_Scn *scn = elf_getscn (elf, 1);
Packit Service 97d2fb
  if (scn == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("couldn't get data section: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  GElf_Shdr shdr_mem;
Packit Service 97d2fb
  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
Packit Service 97d2fb
  if (shdr == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("cannot get header for DATA section: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  if (shdr->sh_size == size)
Packit Service 97d2fb
    printf ("OK %zd bytes.\n", size);
Packit Service 97d2fb
  else
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("BAD size, expected %zd, got %" PRIu64 "\n",
Packit Service 97d2fb
	      size, shdr->sh_size);
Packit Service 97d2fb
      exit (-1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static void
Packit Service 97d2fb
check_section_data (Elf *elf, char *data, size_t len, size_t times)
Packit Service 97d2fb
{
Packit Service 97d2fb
  Elf_Scn *scn = elf_getscn (elf, 1);
Packit Service 97d2fb
  if (scn == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("couldn't get data section: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  Elf_Data *d = NULL;
Packit Service 97d2fb
  for (size_t i = 0; i < times; i++)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      if (d == NULL || i * len >= d->d_off + d->d_size)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  d = elf_getdata (scn, d);
Packit Service 97d2fb
	  if (d == NULL)
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      printf ("cannot get data for section item %zd: %s\n",
Packit Service 97d2fb
		      i, elf_errmsg (-1));
Packit Service 97d2fb
	      exit (1);
Packit Service 97d2fb
	    }
Packit Service 97d2fb
	  else
Packit Service 97d2fb
	    printf ("OK, section data item %zd (d_off: %" PRId64
Packit Service 97d2fb
		    ", d_size: %zd)\n", i, d->d_off, d->d_size);
Packit Service 97d2fb
	}
Packit Service 97d2fb
      char *d_data = (char *) d->d_buf + (len * i) - d->d_off;
Packit Service 97d2fb
      printf ("%zd data (d_off: %" PRId64
Packit Service 97d2fb
	      ", len * i: %zd): (%p + %" PRId64 ") %s\n",
Packit Service 97d2fb
	      i, d->d_off, len * i, d->d_buf, (len * i) - d->d_off, d_data);
Packit Service 97d2fb
      if (memcmp (data, d_data, len) != 0)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  printf ("Got bad data in section for item %zd.\n", i);
Packit Service 97d2fb
	  exit (1);
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static void
Packit Service 97d2fb
check_elf (int class, int use_mmap)
Packit Service 97d2fb
{
Packit Service 97d2fb
  static const char *fname;
Packit Service 97d2fb
  if (class == ELFCLASS32)
Packit Service 97d2fb
    fname = use_mmap ? "newdata.elf32.mmap" : "newdata.elf32";
Packit Service 97d2fb
  else
Packit Service 97d2fb
    fname = use_mmap ? "newdata.elf64.mmap" : "newdata.elf64";
Packit Service 97d2fb
Packit Service 97d2fb
  printf ("\ncheck_elf: %s\n", fname);
Packit Service 97d2fb
Packit Service 97d2fb
  int fd = open (fname, O_RDWR|O_CREAT|O_TRUNC, 00666);
Packit Service 97d2fb
  if (fd == -1)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("cannot create `%s': %s\n", fname, strerror (errno));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  Elf *elf = create_elf (fd, class, use_mmap);
Packit Service 97d2fb
  check_section_size (elf, DATA_LEN);
Packit Service 97d2fb
  check_section_data (elf, DATA, DATA_LEN, 1);
Packit Service 97d2fb
Packit Service 97d2fb
  // Add some more data (won't be written to disk).
Packit Service 97d2fb
  add_section_data (elf, DATA, DATA_LEN);
Packit Service 97d2fb
  check_section_size (elf, 2 * DATA_LEN);
Packit Service 97d2fb
  check_section_data (elf, DATA, DATA_LEN, 2);
Packit Service 97d2fb
Packit Service 97d2fb
  if (elf_end (elf) != 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  close (fd);
Packit Service 97d2fb
Packit Service 97d2fb
  // Read the ELF from disk now.  And add new data directly.
Packit Service 97d2fb
  fd = open (fname, O_RDONLY);
Packit Service 97d2fb
  if (fd == -1)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  elf = read_elf (fd, use_mmap);
Packit Service 97d2fb
  check_section_size (elf, DATA_LEN);
Packit Service 97d2fb
  // But don't check contents, that would read the data...
Packit Service 97d2fb
Packit Service 97d2fb
  // Add some more data.
Packit Service 97d2fb
  add_section_data (elf, DATA, DATA_LEN);
Packit Service 97d2fb
  check_section_size (elf, 2 * DATA_LEN);
Packit Service 97d2fb
  check_section_data (elf, DATA, DATA_LEN, 2);
Packit Service 97d2fb
Packit Service 97d2fb
  // And some more.
Packit Service 97d2fb
  add_section_data (elf, DATA, DATA_LEN);
Packit Service 97d2fb
  check_section_size (elf, 3 * DATA_LEN);
Packit Service 97d2fb
  check_section_data (elf, DATA, DATA_LEN, 3);
Packit Service 97d2fb
Packit Service 97d2fb
  if (elf_end (elf) != 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  close (fd);
Packit Service 97d2fb
Packit Service 97d2fb
  // Read the ELF from disk now.  And add new data after raw reading.
Packit Service 97d2fb
  fd = open (fname, O_RDONLY);
Packit Service 97d2fb
  if (fd == -1)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  elf = read_elf (fd, use_mmap);
Packit Service 97d2fb
  check_section_size (elf, DATA_LEN);
Packit Service 97d2fb
  // But don't check contents, that would read the data...
Packit Service 97d2fb
Packit Service 97d2fb
  // Get raw data before adding new data.
Packit Service 97d2fb
  Elf_Scn *scn = elf_getscn (elf, 1);
Packit Service 97d2fb
  if (scn == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("couldn't get data section: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  printf ("elf_rawdata\n");
Packit Service 97d2fb
  Elf_Data *data = elf_rawdata (scn, NULL);
Packit Service 97d2fb
  if (data == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("couldn't get raw data from section: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  if (data->d_size != DATA_LEN)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("Unexpected Elf_Data: %zd", data->d_size);
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  // Now add more data.
Packit Service 97d2fb
  add_section_data (elf, DATA, DATA_LEN);
Packit Service 97d2fb
  check_section_size (elf, 2 * DATA_LEN);
Packit Service 97d2fb
  check_section_data (elf, DATA, DATA_LEN, 2);
Packit Service 97d2fb
Packit Service 97d2fb
  // And some more.
Packit Service 97d2fb
  add_section_data (elf, DATA, DATA_LEN);
Packit Service 97d2fb
  check_section_size (elf, 3 * DATA_LEN);
Packit Service 97d2fb
  check_section_data (elf, DATA, DATA_LEN, 3);
Packit Service 97d2fb
Packit Service 97d2fb
  if (elf_end (elf) != 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  close (fd);
Packit Service 97d2fb
Packit Service 97d2fb
  // Read the ELF from disk now.  And add new data after data reading.
Packit Service 97d2fb
  fd = open (fname, O_RDONLY);
Packit Service 97d2fb
  if (fd == -1)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  elf = read_elf (fd, use_mmap);
Packit Service 97d2fb
  check_section_size (elf, DATA_LEN);
Packit Service 97d2fb
  // Get (converted) data before adding new data.
Packit Service 97d2fb
  check_section_data (elf, DATA, DATA_LEN, 1);
Packit Service 97d2fb
Packit Service 97d2fb
  printf ("elf_getdata\n");
Packit Service 97d2fb
Packit Service 97d2fb
  // Now add more data.
Packit Service 97d2fb
  add_section_data (elf, DATA, DATA_LEN);
Packit Service 97d2fb
  check_section_size (elf, 2 * DATA_LEN);
Packit Service 97d2fb
  check_section_data (elf, DATA, DATA_LEN, 2);
Packit Service 97d2fb
Packit Service 97d2fb
  // And some more.
Packit Service 97d2fb
  add_section_data (elf, DATA, DATA_LEN);
Packit Service 97d2fb
  check_section_size (elf, 3 * DATA_LEN);
Packit Service 97d2fb
  check_section_data (elf, DATA, DATA_LEN, 3);
Packit Service 97d2fb
Packit Service 97d2fb
  if (elf_end (elf) != 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
Packit Service 97d2fb
      exit (1);
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  close (fd);
Packit Service 97d2fb
Packit Service 97d2fb
  unlink (fname);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
int
Packit Service 97d2fb
main (int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused)))
Packit Service 97d2fb
{
Packit Service 97d2fb
  // Initialize libelf.
Packit Service 97d2fb
  elf_version (EV_CURRENT);
Packit Service 97d2fb
Packit Service 97d2fb
  // Fill holes with something non-zero to more easily spot bad data.
Packit Service 97d2fb
  elf_fill ('X');
Packit Service 97d2fb
Packit Service 97d2fb
  check_elf (ELFCLASS32, 0);
Packit Service 97d2fb
  check_elf (ELFCLASS32, 1);
Packit Service 97d2fb
  check_elf (ELFCLASS64, 0);
Packit Service 97d2fb
  check_elf (ELFCLASS64, 1);
Packit Service 97d2fb
Packit Service 97d2fb
  return 0;
Packit Service 97d2fb
}