Blame libelf/elf32_checksum.c

Packit 032894
/* Compute simple checksum from permanent parts of the ELF file.
Packit 032894
   Copyright (C) 2002, 2003, 2004, 2005, 2009, 2015 Red Hat, Inc.
Packit 032894
   This file is part of elfutils.
Packit 032894
   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
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
#ifdef HAVE_CONFIG_H
Packit 032894
# include <config.h>
Packit 032894
#endif
Packit 032894
Packit 032894
#include <assert.h>
Packit 032894
#include <endian.h>
Packit 032894
#include <stdbool.h>
Packit 032894
#include <stddef.h>
Packit 032894
#include <string.h>
Packit 032894
Packit 032894
#include "gelf.h"
Packit 032894
#include "libelfP.h"
Packit 032894
#include "elf-knowledge.h"
Packit 032894
Packit 032894
#ifndef LIBELFBITS
Packit 032894
# define LIBELFBITS 32
Packit 032894
#endif
Packit 032894
Packit 032894
Packit 032894
#define process_block(crc, data) \
Packit 032894
  __libelf_crc32 (crc, data->d_buf, data->d_size)
Packit 032894
Packit 032894
Packit 032894
long int
Packit 032894
elfw2(LIBELFBITS,checksum) (Elf *elf)
Packit 032894
{
Packit 032894
  size_t shstrndx;
Packit 032894
  Elf_Scn *scn;
Packit 032894
  long int result = 0;
Packit 032894
  unsigned char *ident;
Packit 032894
  bool same_byte_order;
Packit 032894
Packit 032894
  if (elf == NULL)
Packit 032894
    return -1l;
Packit 032894
Packit 032894
  /* Find the section header string table.  */
Packit 032894
  if  (INTUSE(elf_getshdrstrndx) (elf, &shstrndx) < 0)
Packit 032894
    {
Packit 032894
      /* This can only happen if the ELF handle is not for real.  */
Packit 032894
      __libelf_seterrno (ELF_E_INVALID_HANDLE);
Packit 032894
      return -1l;
Packit 032894
    }
Packit 032894
Packit 032894
  /* Determine whether the byte order of the file and that of the host
Packit 032894
     is the same.  */
Packit 032894
  ident = elf->state.ELFW(elf,LIBELFBITS).ehdr->e_ident;
Packit 032894
  same_byte_order = ((ident[EI_DATA] == ELFDATA2LSB
Packit 032894
		      && __BYTE_ORDER == __LITTLE_ENDIAN)
Packit 032894
		     || (ident[EI_DATA] == ELFDATA2MSB
Packit 032894
			 && __BYTE_ORDER == __BIG_ENDIAN));
Packit 032894
Packit 032894
  /* If we don't have native byte order, we will likely need to
Packit 032894
     convert the data with xlate functions.  We do it upfront instead
Packit 032894
     of relocking mid-iteration. */
Packit 032894
  if (!likely (same_byte_order))
Packit 032894
    rwlock_wrlock (elf->lock);
Packit 032894
  else
Packit 032894
    rwlock_rdlock (elf->lock);
Packit 032894
Packit 032894
  /* Iterate over all sections to find those which are not strippable.  */
Packit 032894
  scn = NULL;
Packit 032894
  while ((scn = INTUSE(elf_nextscn) (elf, scn)) != NULL)
Packit 032894
    {
Packit 032894
      GElf_Shdr shdr_mem;
Packit 032894
      GElf_Shdr *shdr;
Packit 032894
      Elf_Data *data;
Packit 032894
Packit 032894
      /* Get the section header.  */
Packit 032894
      shdr = INTUSE(gelf_getshdr) (scn, &shdr_mem);
Packit 032894
      if (shdr == NULL)
Packit 032894
	{
Packit 032894
	  __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
Packit 032894
	  result = -1l;
Packit 032894
	  goto out;
Packit 032894
	}
Packit 032894
Packit 032894
      if (SECTION_STRIP_P (shdr,
Packit 032894
			   INTUSE(elf_strptr) (elf, shstrndx, shdr->sh_name),
Packit 032894
			   true))
Packit 032894
	/* The section can be stripped.  Don't use it.  */
Packit 032894
	continue;
Packit 032894
Packit 032894
      /* Do not look at NOBITS sections.  */
Packit 032894
      if (shdr->sh_type == SHT_NOBITS)
Packit 032894
	continue;
Packit 032894
Packit 032894
      /* To compute the checksum we need to get to the data.  For
Packit 032894
	 repeatable results we must use the external format.  The data
Packit 032894
	 we get with 'elf'getdata' might be changed for endianess
Packit 032894
	 reasons.  Therefore we use 'elf_rawdata' if possible.  But
Packit 032894
	 this function can fail if the data was constructed by the
Packit 032894
	 program.  In this case we have to use 'elf_getdata' and
Packit 032894
	 eventually convert the data to the external format.  */
Packit 032894
      data = INTUSE(elf_rawdata) (scn, NULL);
Packit 032894
      if (data != NULL)
Packit 032894
	{
Packit 032894
	  /* The raw data is available.  */
Packit 032894
	  result = process_block (result, data);
Packit 032894
Packit 032894
	  /* Maybe the user added more data.  These blocks cannot be
Packit 032894
	     read using 'elf_rawdata'.  Simply proceed with looking
Packit 032894
	     for more data block with 'elf_getdata'.  */
Packit 032894
	}
Packit 032894
Packit 032894
      /* Iterate through the list of data blocks.  */
Packit 032894
      while ((data = INTUSE(elf_getdata) (scn, data)) != NULL)
Packit 032894
	/* If the file byte order is the same as the host byte order
Packit 032894
	   process the buffer directly.  If the data is just a stream
Packit 032894
	   of bytes which the library will not convert we can use it
Packit 032894
	   as well.  */
Packit 032894
	if (likely (same_byte_order) || data->d_type == ELF_T_BYTE)
Packit 032894
	  result = process_block (result, data);
Packit 032894
	else
Packit 032894
	  {
Packit 032894
	    /* Convert the data to file byte order.  */
Packit 032894
	    if (INTUSE(elfw2(LIBELFBITS,xlatetof)) (data, data, ident[EI_DATA])
Packit 032894
		== NULL)
Packit 032894
	      {
Packit 032894
		result = -1l;
Packit 032894
		goto out;
Packit 032894
	      }
Packit 032894
Packit 032894
	    result = process_block (result, data);
Packit 032894
Packit 032894
	    /* And convert it back.  */
Packit 032894
	    if (INTUSE(elfw2(LIBELFBITS,xlatetom)) (data, data, ident[EI_DATA])
Packit 032894
		== NULL)
Packit 032894
	      {
Packit 032894
		result = -1l;
Packit 032894
		goto out;
Packit 032894
	      }
Packit 032894
	  }
Packit 032894
    }
Packit 032894
Packit 032894
 out:
Packit 032894
  rwlock_unlock (elf->lock);
Packit 032894
  return result;
Packit 032894
}
Packit 032894
INTDEF(elfw2(LIBELFBITS,checksum))