My intention is to read an ELF file, then append some data to the end of a
section, then update the existing ELF file.
I wrote a small example program that works fine with libelfg0, but it fails
to append with elfutils (it replaces the data instead of appending to it).

The following is observed on Ubuntu-11.10 (installed version of libelf1 is
0.152). I have attached a small example program that demonstrates the
behavior.

With libelfg0 version 0.8.13 the effect of the elf_newdata() call is to
__append__ the new data buffer to the end of any existing data in a section.
However, with libelf1 the elf_newdata() call actually __replaces__ existing
data when elf_update() executes.

The man page at
http://docs.oracle.com/cd/E19253-01/816-5172/elf-getdata-3elf/index.htmlsuggests
that appending is the intended behavior. Can anyone confirm this?
It would be very inconvenient to have two libraries in the world that seem
to provide the same source-level API but with slightly different semantics
...

Thanks for clearing this up,
Paul Stravers
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <libelf.h>
#include <gelf.h>

void __attribute__ ((noreturn)) err(const char *msg, ...)
{
  va_list ap;
  va_start(ap,msg);
  fprintf(stderr,"Error: ");
  vfprintf(stderr,msg,ap);
  fprintf(stderr,"\n");
  fflush(stderr);
  exit(1);
  va_end(ap);
}

Elf_Scn *get_symbol_strtab(Elf *elf)
{
  Elf_Scn *scn = NULL;
  while ((scn = elf_nextscn(elf, scn)) != NULL)
  {
    GElf_Shdr shdr;
    gelf_getshdr(scn, &shdr);
    if (shdr.sh_type == SHT_SYMTAB)
    {
      GElf_Shdr symtab_shdr;
      gelf_getshdr(scn, &symtab_shdr);
      size_t strtab_ndx = symtab_shdr.sh_link;
      return elf_getscn(elf, strtab_ndx);
    }
  }
  return NULL;
}


int main(int argc, const char *argv[])
{
  /* ***** open an ELF object in read/write mode *****
   */
  if (argc != 2)
    err("Usage: %s elf_file", argv[0]);
  const char *elf_file = argv[1];
  if (elf_version(EV_CURRENT) == EV_NONE)
    err("ELF library is out-dated, cannot handle ELF object");
  int elf_fd = open(elf_file, O_RDWR);
  if (elf_fd == -1)
    err("cannot open %s", elf_file);
  Elf *elf = elf_begin(elf_fd, ELF_C_RDWR, NULL);
  Elf_Kind kind = elf_kind(elf);
  if (kind != ELF_K_ELF)
    err("%s is not an ELF object", elf_file);

  /* ***** append a string to first STRTAB in the object *****
   */
  Elf_Scn *strtab_scn = get_symbol_strtab(elf);
  if (strtab_scn == NULL)
    err("cannot find strtab");
  Elf_Data *data = elf_newdata(strtab_scn);
  /* NOTE: with libelfg0 version 0.8.13 the effect of the
   * elf_newdata() call is to append the new data buffer to the end of
   * the existing data in strtab_scn. HOWEVER, with libelf1 the
   * elf_newdata() actually __replaces__ the existing data when
   * elf_update() executes (on Ubuntu-11.10). The man page at
   * http://docs.oracle.com/cd/E19253-01/816-5172/elf-getdata-3elf/index.html
   * suggest that appending is the intended behavior.
   */
  char *append_this = strdup("append_this");
  data->d_buf = append_this;
  data->d_size = 1 + strlen(append_this);
  data->d_align = 0;
  data->d_type = ELF_T_BYTE;

  /* ***** write-back the updated image to the ELF file *****
   */
  loff_t file_sz = elf_update(elf, ELF_C_WRITE);
  if (file_sz == -1)
    err("cannot update ELF image");
  printf("Updated object file %s with new size %lld\n", elf_file, (long long)file_sz);
  if (elf_end(elf) != 0)
    err("cannot terminate ELF editing session");
  if (close(elf_fd) == -1)
    err("cannot close ELF object file %s", elf_file);
  return 0;
}
_______________________________________________
elfutils-devel mailing list
[email protected]
https://lists.fedorahosted.org/mailman/listinfo/elfutils-devel

Reply via email to