This is the mail archive of the elfutils-devel@sourceware.org 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]

Re: mpolacek/ebl_dynamic_tag_name


On 03/25/2011 04:27 PM, Marek Polacek wrote:
> Ok, another try.  I've constructed an ELF file with all the
> DT_* flags set, it is named testfile58.

FWIW, here is source code of program which constructs an ELF
file like this:


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

   Red Hat elfutils 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; version 2 of the License.

   Red Hat 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 Red Hat elfutils; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.

   Red Hat elfutils is an included package of the Open Invention Network.
   An included package of the Open Invention Network is a package for which
   Open Invention Network licensees cross-license their patents.  No patent
   license is granted, either expressly or impliedly, by designation as an
   included package.  Should you wish to participate in the Open Invention
   Network licensing program, please visit www.openinventionnetwork.com
   <http://www.openinventionnetwork.com>.  */

#include <elf.h>
#include <gelf.h>
#include <fcntl.h>
#include <libelf.h>
#include <libebl.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[] = "testfile58";
  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;
}

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