Blame libelf/version_xlate.h

Packit 032894
/* Conversion functions for versioning information.
Packit 032894
   Copyright (C) 1998, 1999, 2000, 2002, 2003, 2015 Red Hat, Inc.
Packit 032894
   This file is part of elfutils.
Packit 032894
   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
Packit 032894
Packit 032894
   This file is free software; you can redistribute it and/or modify
Packit 032894
   it under the terms of either
Packit 032894
Packit 032894
     * the GNU Lesser General Public License as published by the Free
Packit 032894
       Software Foundation; either version 3 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or
Packit 032894
Packit 032894
     * the GNU General Public License as published by the Free
Packit 032894
       Software Foundation; either version 2 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or both in parallel, as here.
Packit 032894
Packit 032894
   elfutils is distributed in the hope that it will be useful, but
Packit 032894
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 032894
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 032894
   General Public License for more details.
Packit 032894
Packit 032894
   You should have received copies of the GNU General Public License and
Packit 032894
   the GNU Lesser General Public License along with this program.  If
Packit 032894
   not, see <http://www.gnu.org/licenses/>.  */
Packit 032894
Packit 032894
#include <assert.h>
Packit 032894
#include <gelf.h>
Packit 032894
Packit 032894
#include "libelfP.h"
Packit 032894
Packit 032894
Packit 032894
static void
Packit 032894
elf_cvt_Verdef (void *dest, const void *src, size_t len, int encode)
Packit 032894
{
Packit 032894
  /* We have two different record types: ElfXX_Verndef and ElfXX_Verdaux.
Packit 032894
     To recognize them we have to walk the data structure and convert
Packit 032894
     them one after the other.  The ENCODE parameter specifies whether
Packit 032894
     we are encoding or decoding.  When we are encoding we can immediately
Packit 032894
     use the data in the buffer; if not, we have to decode the data before
Packit 032894
     using it.  */
Packit 032894
  size_t def_offset = 0;
Packit 032894
  GElf_Verdef *ddest;
Packit 032894
  GElf_Verdef *dsrc;
Packit 032894
Packit 032894
  /* We rely on the types being all the same size.  */
Packit 032894
  assert (sizeof (GElf_Verdef) == sizeof (Elf32_Verdef));
Packit 032894
  assert (sizeof (GElf_Verdaux) == sizeof (Elf32_Verdaux));
Packit 032894
  assert (sizeof (GElf_Verdef) == sizeof (Elf64_Verdef));
Packit 032894
  assert (sizeof (GElf_Verdaux) == sizeof (Elf64_Verdaux));
Packit 032894
Packit 032894
  if (len == 0)
Packit 032894
    return;
Packit 032894
Packit 032894
  /* Below we rely on the next field offsets to be correct, start by
Packit 032894
     copying over all data as is in case some data isn't translated.
Packit 032894
     We don't want to leave (undefined) garbage in the dest buffer.  */
Packit 032894
  memmove (dest, src, len);
Packit 032894
Packit 032894
  do
Packit 032894
    {
Packit 032894
      size_t aux_offset;
Packit 032894
      GElf_Verdaux *asrc;
Packit 032894
Packit 032894
      /* Test for correct offset.  */
Packit 032894
      if (def_offset > len || len - def_offset < sizeof (GElf_Verdef))
Packit 032894
	return;
Packit 032894
Packit 032894
      /* Work the tree from the first record.  */
Packit 032894
      ddest = (GElf_Verdef *) ((char *) dest + def_offset);
Packit 032894
      dsrc = (GElf_Verdef *) ((char *) src + def_offset);
Packit 032894
Packit 032894
      /* Decode first if necessary.  */
Packit 032894
      if (! encode)
Packit 032894
	{
Packit 032894
	  ddest->vd_version = bswap_16 (dsrc->vd_version);
Packit 032894
	  ddest->vd_flags = bswap_16 (dsrc->vd_flags);
Packit 032894
	  ddest->vd_ndx = bswap_16 (dsrc->vd_ndx);
Packit 032894
	  ddest->vd_cnt = bswap_16 (dsrc->vd_cnt);
Packit 032894
	  ddest->vd_hash = bswap_32 (dsrc->vd_hash);
Packit 032894
	  ddest->vd_aux = bswap_32 (dsrc->vd_aux);
Packit 032894
	  ddest->vd_next = bswap_32 (dsrc->vd_next);
Packit 032894
Packit 032894
	  aux_offset = def_offset + ddest->vd_aux;
Packit 032894
	}
Packit 032894
      else
Packit 032894
	aux_offset = def_offset + dsrc->vd_aux;
Packit 032894
Packit 032894
      /* Handle all the auxiliary records belonging to this definition.  */
Packit 032894
      do
Packit 032894
	{
Packit 032894
	  GElf_Verdaux *adest;
Packit 032894
Packit 032894
	  /* Test for correct offset.  */
Packit 032894
	  if (aux_offset > len || len - aux_offset < sizeof (GElf_Verdaux))
Packit 032894
	    return;
Packit 032894
Packit 032894
	  adest = (GElf_Verdaux *) ((char *) dest + aux_offset);
Packit 032894
	  asrc = (GElf_Verdaux *) ((char *) src + aux_offset);
Packit 032894
Packit 032894
	  if (encode)
Packit 032894
	    aux_offset += asrc->vda_next;
Packit 032894
Packit 032894
	  adest->vda_name = bswap_32 (asrc->vda_name);
Packit 032894
	  adest->vda_next = bswap_32 (asrc->vda_next);
Packit 032894
Packit 032894
	  if (! encode)
Packit 032894
	    aux_offset += adest->vda_next;
Packit 032894
	}
Packit 032894
      while (asrc->vda_next != 0);
Packit 032894
Packit 032894
      /* Encode now if necessary.  */
Packit 032894
      if (encode)
Packit 032894
	{
Packit 032894
	  def_offset += dsrc->vd_next;
Packit 032894
Packit 032894
	  ddest->vd_version = bswap_16 (dsrc->vd_version);
Packit 032894
	  ddest->vd_flags = bswap_16 (dsrc->vd_flags);
Packit 032894
	  ddest->vd_ndx = bswap_16 (dsrc->vd_ndx);
Packit 032894
	  ddest->vd_cnt = bswap_16 (dsrc->vd_cnt);
Packit 032894
	  ddest->vd_hash = bswap_32 (dsrc->vd_hash);
Packit 032894
	  ddest->vd_aux = bswap_32 (dsrc->vd_aux);
Packit 032894
	  ddest->vd_next = bswap_32 (dsrc->vd_next);
Packit 032894
	}
Packit 032894
      else
Packit 032894
	def_offset += ddest->vd_next;
Packit 032894
    }
Packit 032894
  while (dsrc->vd_next != 0);
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static void
Packit 032894
elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
Packit 032894
{
Packit 032894
  /* We have two different record types: ElfXX_Verndef and ElfXX_Verdaux.
Packit 032894
     To recognize them we have to walk the data structure and convert
Packit 032894
     them one after the other.  The ENCODE parameter specifies whether
Packit 032894
     we are encoding or decoding.  When we are encoding we can immediately
Packit 032894
     use the data in the buffer; if not, we have to decode the data before
Packit 032894
     using it.  */
Packit 032894
  size_t need_offset = 0;
Packit 032894
  GElf_Verneed *ndest;
Packit 032894
  GElf_Verneed *nsrc;
Packit 032894
Packit 032894
  /* We rely on the types being all the same size.  */
Packit 032894
  assert (sizeof (GElf_Verneed) == sizeof (Elf32_Verneed));
Packit 032894
  assert (sizeof (GElf_Vernaux) == sizeof (Elf32_Vernaux));
Packit 032894
  assert (sizeof (GElf_Verneed) == sizeof (Elf64_Verneed));
Packit 032894
  assert (sizeof (GElf_Vernaux) == sizeof (Elf64_Vernaux));
Packit 032894
Packit 032894
  if (len == 0)
Packit 032894
    return;
Packit 032894
Packit 032894
  /* Below we rely on the next field offsets to be correct, start by
Packit 032894
     copying over all data as is in case some data isn't translated.
Packit 032894
     We don't want to leave (undefined) garbage in the dest buffer.  */
Packit 032894
  memmove (dest, src, len);
Packit 032894
Packit 032894
  do
Packit 032894
    {
Packit 032894
      size_t aux_offset;
Packit 032894
      GElf_Vernaux *asrc;
Packit 032894
Packit 032894
      /* Test for correct offset.  */
Packit 032894
      if (need_offset > len || len - need_offset < sizeof (GElf_Verneed))
Packit 032894
	return;
Packit 032894
Packit 032894
      /* Work the tree from the first record.  */
Packit 032894
      ndest = (GElf_Verneed *) ((char *) dest + need_offset);
Packit 032894
      nsrc = (GElf_Verneed *) ((char *) src + need_offset);
Packit 032894
Packit 032894
      /* Decode first if necessary.  */
Packit 032894
      if (! encode)
Packit 032894
	{
Packit 032894
	  ndest->vn_version = bswap_16 (nsrc->vn_version);
Packit 032894
	  ndest->vn_cnt = bswap_16 (nsrc->vn_cnt);
Packit 032894
	  ndest->vn_file = bswap_32 (nsrc->vn_file);
Packit 032894
	  ndest->vn_aux = bswap_32 (nsrc->vn_aux);
Packit 032894
	  ndest->vn_next = bswap_32 (nsrc->vn_next);
Packit 032894
Packit 032894
	  aux_offset = need_offset + ndest->vn_aux;
Packit 032894
	}
Packit 032894
      else
Packit 032894
	aux_offset = need_offset + nsrc->vn_aux;
Packit 032894
Packit 032894
      /* Handle all the auxiliary records belonging to this requirement.  */
Packit 032894
      do
Packit 032894
	{
Packit 032894
	  GElf_Vernaux *adest;
Packit 032894
Packit 032894
	  /* Test for correct offset.  */
Packit 032894
	  if (aux_offset > len || len - aux_offset < sizeof (GElf_Vernaux))
Packit 032894
	    return;
Packit 032894
Packit 032894
	  adest = (GElf_Vernaux *) ((char *) dest + aux_offset);
Packit 032894
	  asrc = (GElf_Vernaux *) ((char *) src + aux_offset);
Packit 032894
Packit 032894
	  if (encode)
Packit 032894
	    aux_offset += asrc->vna_next;
Packit 032894
Packit 032894
	  adest->vna_hash = bswap_32 (asrc->vna_hash);
Packit 032894
	  adest->vna_flags = bswap_16 (asrc->vna_flags);
Packit 032894
	  adest->vna_other = bswap_16 (asrc->vna_other);
Packit 032894
	  adest->vna_name = bswap_32 (asrc->vna_name);
Packit 032894
	  adest->vna_next = bswap_32 (asrc->vna_next);
Packit 032894
Packit 032894
	  if (! encode)
Packit 032894
	    aux_offset += adest->vna_next;
Packit 032894
	}
Packit 032894
      while (asrc->vna_next != 0);
Packit 032894
Packit 032894
      /* Encode now if necessary.  */
Packit 032894
      if (encode)
Packit 032894
	{
Packit 032894
	  need_offset += nsrc->vn_next;
Packit 032894
Packit 032894
	  ndest->vn_version = bswap_16 (nsrc->vn_version);
Packit 032894
	  ndest->vn_cnt = bswap_16 (nsrc->vn_cnt);
Packit 032894
	  ndest->vn_file = bswap_32 (nsrc->vn_file);
Packit 032894
	  ndest->vn_aux = bswap_32 (nsrc->vn_aux);
Packit 032894
	  ndest->vn_next = bswap_32 (nsrc->vn_next);
Packit 032894
	}
Packit 032894
      else
Packit 032894
	need_offset += ndest->vn_next;
Packit 032894
    }
Packit 032894
  while (nsrc->vn_next != 0);
Packit 032894
}