/* Create an ELF file with all the DT_* flags set.
   Copyright (C) 2011 Red Hat, Inc.
   This file is part of elfutils.
   Written by Marek Polacek <mpolacek@redhat.com>, 2011.

   This file is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   elfutils is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include ELFUTILS_HEADER(ebl)
#include <elf.h>
#include <gelf.h>
#include <fcntl.h>
#include <libelf.h>
#include <stdio.h>
#include <stdio_ext.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>


int
main (void)
{
  static const char fname[] = "testfile-alldts";
  struct Ebl_Strtab *shst;
  struct Ebl_Strent *dynscn;
  struct Ebl_Strent *shstrtabse;
  const Elf32_Sword dtflags[] =
    {
      DT_NULL, DT_NEEDED, DT_PLTRELSZ, DT_PLTGOT,
      DT_HASH, DT_STRTAB, DT_SYMTAB, DT_RELA,
      DT_RELASZ, DT_RELAENT, DT_STRSZ, DT_SYMENT,
      DT_INIT, DT_FINI, DT_SONAME, DT_RPATH,
      DT_SYMBOLIC, DT_REL, DT_RELSZ, DT_RELENT,
      DT_PLTREL, DT_DEBUG, DT_TEXTREL, DT_JMPREL,
      DT_BIND_NOW, DT_INIT_ARRAY, DT_FINI_ARRAY,
      DT_INIT_ARRAYSZ, DT_FINI_ARRAYSZ, DT_RUNPATH,
      DT_FLAGS, DT_ENCODING, DT_PREINIT_ARRAY,
      DT_PREINIT_ARRAYSZ, DT_VERSYM, DT_GNU_PRELINKED,
      DT_GNU_CONFLICTSZ, DT_GNU_LIBLISTSZ, DT_CHECKSUM,
      DT_PLTPADSZ, DT_MOVEENT, DT_MOVESZ, DT_FEATURE_1,
      DT_POSFLAG_1, DT_SYMINSZ, DT_SYMINENT, DT_GNU_HASH,
      DT_TLSDESC_PLT, DT_TLSDESC_GOT, DT_GNU_CONFLICT,
      DT_GNU_LIBLIST, DT_CONFIG, DT_DEPAUDIT, DT_AUDIT,
      DT_PLTPAD, DT_MOVETAB, DT_SYMINFO, DT_RELACOUNT,
      DT_RELCOUNT, DT_FLAGS_1, DT_VERDEF, DT_VERDEFNUM,
      DT_VERNEED, DT_VERNEEDNUM, DT_AUXILIARY, DT_FILTER
    };
  const int ndtflags = sizeof (dtflags) / sizeof (dtflags[0]);

  /* We use no threads here which can interfere with handling a stream.  */
  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);

  /* Open the file.  */
  int fd = open64 (fname, O_RDWR | O_CREAT | O_TRUNC, 0666);
  if (fd == -1)
    {
      printf ("cannot open `%s': %m\n", fname);
      return 1;
    }

  /* Tell the library which version are we expecting.  */
  elf_version (EV_CURRENT);

  /* Create an ELF descriptor.  */
  Elf *elf = elf_begin (fd, ELF_C_WRITE, NULL);
  if (elf == NULL)
    {
      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
      return 1;
    }

  /* Create an ELF header.  */
  Elf32_Ehdr *ehdr = elf32_newehdr (elf);
  if (ehdr == NULL)
    {
      printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
      return 1;
    }

  ehdr->e_ident[0] = 42;
  ehdr->e_ident[5] = 1;
  ehdr->e_ident[6] = 2;
  ehdr->e_type = ET_EXEC;
  ehdr->e_machine = EM_386;
  ehdr->e_version = 1;
  ehdr->e_ehsize = 1;
  ehdr->e_shnum = 3;

  elf_flagehdr (elf, ELF_C_SET, ELF_F_DIRTY);

  /* Create the program headers.  */
  Elf32_Phdr *phdr = elf32_newphdr (elf, 2);
  if (phdr == NULL)
    {
      printf ("cannot create program headers: %s\n", elf_errmsg (-1));
      return 1;
    }

  phdr[0].p_type = PT_PHDR;
  phdr[1].p_type = PT_DYNAMIC;

  elf_flagphdr (elf, ELF_C_SET, ELF_F_DIRTY);
  shst = ebl_strtabinit (true);

  /* Create the .dynamic section.  */
  Elf_Scn *scn = elf_newscn (elf);
  if (scn == NULL)
    {
      printf ("cannot create DYNAMIC section: %s\n", elf_errmsg (-1));
      return 1;
    }

  Elf32_Shdr *shdr = elf32_getshdr (scn);
  if (shdr == NULL)
    {
      printf ("cannot get header for DYNAMIC section: %s\n", elf_errmsg (-1));
      return 1;
    }

  dynscn = ebl_strtabadd (shst, ".dynamic", 0);

  /* We'll need to know the section offset.  But this will be set up
     by elf_update later, so for now just store the address.  */
  const Elf32_Off *const dynscn_offset = &shdr->sh_offset;
  shdr->sh_type = SHT_DYNAMIC;
  shdr->sh_flags = SHF_ALLOC | SHF_WRITE;
  shdr->sh_link = SHN_UNDEF;
  shdr->sh_info = SHN_UNDEF;
  /* This section will start here.  */
  shdr->sh_addr = 0x1a0;

  /* Create new section data.  */
  Elf_Data *data = elf_newdata (scn);
  if (data == NULL)
    {
      printf ("cannot create data for DYNAMIC section: %s\n", elf_errmsg (-1));
      return 1;
    }

  /* Allocate memory for all the .dynamic entries.  */
  Elf32_Dyn *dyn = malloc (ndtflags * sizeof (Elf32_Dyn));
  if (dyn == NULL)
    {
      printf ("malloc failed: %m\n");
      return 1;
    }

  /* Now write all the DT_* flags.  */
  for (int i = 0; i < ndtflags; ++i)
    {
      dyn[i].d_tag = dtflags[i];
      dyn[i].d_un.d_val = 0xdeadbeef;
    }

  /* Set the pointer to allocated memory.  */
  data->d_buf = dyn;
  data->d_type = ELF_T_DYN;
  data->d_version = EV_CURRENT;
  data->d_size = ndtflags * sizeof (Elf32_Dyn);
  data->d_align = 0x8;

  /* Create .shstrtab section.  */
  scn = elf_newscn (elf);
  if (scn == NULL)
    {
      printf ("cannot create SHSTRTAB section: %s\n", elf_errmsg (-1));
      return 1;
    }

  shdr = elf32_getshdr (scn);
  if (shdr == NULL)
    {
      printf ("cannot get header for SHSTRTAB section: %s\n", elf_errmsg (-1));
      return 1;
    }

  shstrtabse = ebl_strtabadd (shst, ".shstrtab", 0);

  shdr->sh_type = SHT_STRTAB;
  shdr->sh_flags = 0;
  shdr->sh_addr = 0;
  shdr->sh_link = SHN_UNDEF;
  shdr->sh_info = SHN_UNDEF;
  shdr->sh_entsize = 1;

  /* We have to store the section index in the ELF header.  */
  ehdr->e_shstrndx = elf_ndxscn (scn);

  data = elf_newdata (scn);
  if (data == NULL)
    {
      printf ("cannot create data SHSTRTAB section: %s\n", elf_errmsg (-1));
      return 1;
    }

  /* No more sections, finalize the section header string table.  */
  ebl_strtabfinalize (shst, data);

  elf32_getshdr (elf_getscn (elf, 1))->sh_name = ebl_strtaboffset (dynscn);
  shdr->sh_name = ebl_strtaboffset (shstrtabse);

  /* Let the library compute the internal structure information.  */
  if (elf_update (elf, ELF_C_NULL) < 0)
    {
      printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1));
      return 1;
    }

  ehdr = elf32_getehdr (elf);

  phdr[0].p_offset = ehdr->e_phoff;
  phdr[0].p_vaddr = ehdr->e_phoff;
  phdr[0].p_paddr = ehdr->e_phoff;
  phdr[0].p_flags = PF_R | PF_X;
  phdr[0].p_filesz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT);
  phdr[0].p_memsz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT);
  phdr[0].p_align = sizeof (Elf32_Word);

  phdr[1].p_flags = PF_W | PF_R;
  phdr[1].p_offset = *dynscn_offset;
  /* Set up the start of this segment to equal start address of the
     .dynamic section.  */
  phdr[1].p_vaddr = 0x1a0;
  phdr[1].p_paddr = 0x1a0;
  phdr[1].p_align = 2 * sizeof (Elf32_Word);
  phdr[1].p_filesz = ndtflags * sizeof (Elf32_Dyn);
  phdr[1].p_memsz = ndtflags * sizeof (Elf32_Dyn);

  /* Write out the file.  */
  if (elf_update (elf, ELF_C_WRITE) < 0)
    {
      printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
      return 1;
    }

  /* We don't need the string table anymore.  */
  ebl_strtabfree (shst);

  /* And the data allocated in the .shstrtab section.  */
  free (data->d_buf);

  /* All done.  */
  if (elf_end (elf) != 0)
    {
      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
      return 1;
    }

  return 0;
}
