1da0c48c4Sopenharmony_ci/* Compute simple checksum from permanent parts of the ELF file. 2da0c48c4Sopenharmony_ci Copyright (C) 2002, 2003, 2004, 2005, 2009, 2015 Red Hat, Inc. 3da0c48c4Sopenharmony_ci This file is part of elfutils. 4da0c48c4Sopenharmony_ci Written by Ulrich Drepper <drepper@redhat.com>, 2002. 5da0c48c4Sopenharmony_ci 6da0c48c4Sopenharmony_ci This file is free software; you can redistribute it and/or modify 7da0c48c4Sopenharmony_ci it under the terms of either 8da0c48c4Sopenharmony_ci 9da0c48c4Sopenharmony_ci * the GNU Lesser General Public License as published by the Free 10da0c48c4Sopenharmony_ci Software Foundation; either version 3 of the License, or (at 11da0c48c4Sopenharmony_ci your option) any later version 12da0c48c4Sopenharmony_ci 13da0c48c4Sopenharmony_ci or 14da0c48c4Sopenharmony_ci 15da0c48c4Sopenharmony_ci * the GNU General Public License as published by the Free 16da0c48c4Sopenharmony_ci Software Foundation; either version 2 of the License, or (at 17da0c48c4Sopenharmony_ci your option) any later version 18da0c48c4Sopenharmony_ci 19da0c48c4Sopenharmony_ci or both in parallel, as here. 20da0c48c4Sopenharmony_ci 21da0c48c4Sopenharmony_ci elfutils is distributed in the hope that it will be useful, but 22da0c48c4Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 23da0c48c4Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24da0c48c4Sopenharmony_ci General Public License for more details. 25da0c48c4Sopenharmony_ci 26da0c48c4Sopenharmony_ci You should have received copies of the GNU General Public License and 27da0c48c4Sopenharmony_ci the GNU Lesser General Public License along with this program. If 28da0c48c4Sopenharmony_ci not, see <http://www.gnu.org/licenses/>. */ 29da0c48c4Sopenharmony_ci 30da0c48c4Sopenharmony_ci#ifdef HAVE_CONFIG_H 31da0c48c4Sopenharmony_ci# include <config.h> 32da0c48c4Sopenharmony_ci#endif 33da0c48c4Sopenharmony_ci 34da0c48c4Sopenharmony_ci#include <assert.h> 35da0c48c4Sopenharmony_ci#include <stdbool.h> 36da0c48c4Sopenharmony_ci#include <stddef.h> 37da0c48c4Sopenharmony_ci#include <string.h> 38da0c48c4Sopenharmony_ci 39da0c48c4Sopenharmony_ci#include "gelf.h" 40da0c48c4Sopenharmony_ci#include "libelfP.h" 41da0c48c4Sopenharmony_ci#include "elf-knowledge.h" 42da0c48c4Sopenharmony_ci 43da0c48c4Sopenharmony_ci#ifndef LIBELFBITS 44da0c48c4Sopenharmony_ci# define LIBELFBITS 32 45da0c48c4Sopenharmony_ci#endif 46da0c48c4Sopenharmony_ci 47da0c48c4Sopenharmony_ci 48da0c48c4Sopenharmony_ci#define process_block(crc, data) \ 49da0c48c4Sopenharmony_ci __libelf_crc32 (crc, data->d_buf, data->d_size) 50da0c48c4Sopenharmony_ci 51da0c48c4Sopenharmony_ci 52da0c48c4Sopenharmony_cilong int 53da0c48c4Sopenharmony_cielfw2(LIBELFBITS,checksum) (Elf *elf) 54da0c48c4Sopenharmony_ci{ 55da0c48c4Sopenharmony_ci size_t shstrndx; 56da0c48c4Sopenharmony_ci Elf_Scn *scn; 57da0c48c4Sopenharmony_ci long int result = 0; 58da0c48c4Sopenharmony_ci unsigned char *ident; 59da0c48c4Sopenharmony_ci bool same_byte_order; 60da0c48c4Sopenharmony_ci 61da0c48c4Sopenharmony_ci if (elf == NULL) 62da0c48c4Sopenharmony_ci return -1l; 63da0c48c4Sopenharmony_ci 64da0c48c4Sopenharmony_ci /* Find the section header string table. */ 65da0c48c4Sopenharmony_ci if (INTUSE(elf_getshdrstrndx) (elf, &shstrndx) < 0) 66da0c48c4Sopenharmony_ci { 67da0c48c4Sopenharmony_ci /* This can only happen if the ELF handle is not for real. */ 68da0c48c4Sopenharmony_ci __libelf_seterrno (ELF_E_INVALID_HANDLE); 69da0c48c4Sopenharmony_ci return -1l; 70da0c48c4Sopenharmony_ci } 71da0c48c4Sopenharmony_ci 72da0c48c4Sopenharmony_ci /* Determine whether the byte order of the file and that of the host 73da0c48c4Sopenharmony_ci is the same. */ 74da0c48c4Sopenharmony_ci ident = elf->state.ELFW(elf,LIBELFBITS).ehdr->e_ident; 75da0c48c4Sopenharmony_ci same_byte_order = ((ident[EI_DATA] == ELFDATA2LSB 76da0c48c4Sopenharmony_ci && BYTE_ORDER == LITTLE_ENDIAN) 77da0c48c4Sopenharmony_ci || (ident[EI_DATA] == ELFDATA2MSB 78da0c48c4Sopenharmony_ci && BYTE_ORDER == BIG_ENDIAN)); 79da0c48c4Sopenharmony_ci 80da0c48c4Sopenharmony_ci /* If we don't have native byte order, we will likely need to 81da0c48c4Sopenharmony_ci convert the data with xlate functions. We do it upfront instead 82da0c48c4Sopenharmony_ci of relocking mid-iteration. */ 83da0c48c4Sopenharmony_ci if (!likely (same_byte_order)) 84da0c48c4Sopenharmony_ci rwlock_wrlock (elf->lock); 85da0c48c4Sopenharmony_ci else 86da0c48c4Sopenharmony_ci rwlock_rdlock (elf->lock); 87da0c48c4Sopenharmony_ci 88da0c48c4Sopenharmony_ci /* Iterate over all sections to find those which are not strippable. */ 89da0c48c4Sopenharmony_ci scn = NULL; 90da0c48c4Sopenharmony_ci while ((scn = INTUSE(elf_nextscn) (elf, scn)) != NULL) 91da0c48c4Sopenharmony_ci { 92da0c48c4Sopenharmony_ci GElf_Shdr shdr_mem; 93da0c48c4Sopenharmony_ci GElf_Shdr *shdr; 94da0c48c4Sopenharmony_ci Elf_Data *data; 95da0c48c4Sopenharmony_ci 96da0c48c4Sopenharmony_ci /* Get the section header. */ 97da0c48c4Sopenharmony_ci shdr = INTUSE(gelf_getshdr) (scn, &shdr_mem); 98da0c48c4Sopenharmony_ci if (shdr == NULL) 99da0c48c4Sopenharmony_ci { 100da0c48c4Sopenharmony_ci __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER); 101da0c48c4Sopenharmony_ci result = -1l; 102da0c48c4Sopenharmony_ci goto out; 103da0c48c4Sopenharmony_ci } 104da0c48c4Sopenharmony_ci 105da0c48c4Sopenharmony_ci if (SECTION_STRIP_P (shdr, 106da0c48c4Sopenharmony_ci INTUSE(elf_strptr) (elf, shstrndx, shdr->sh_name), 107da0c48c4Sopenharmony_ci true)) 108da0c48c4Sopenharmony_ci /* The section can be stripped. Don't use it. */ 109da0c48c4Sopenharmony_ci continue; 110da0c48c4Sopenharmony_ci 111da0c48c4Sopenharmony_ci /* Do not look at NOBITS sections. */ 112da0c48c4Sopenharmony_ci if (shdr->sh_type == SHT_NOBITS) 113da0c48c4Sopenharmony_ci continue; 114da0c48c4Sopenharmony_ci 115da0c48c4Sopenharmony_ci /* To compute the checksum we need to get to the data. For 116da0c48c4Sopenharmony_ci repeatable results we must use the external format. The data 117da0c48c4Sopenharmony_ci we get with 'elf'getdata' might be changed for endianness 118da0c48c4Sopenharmony_ci reasons. Therefore we use 'elf_rawdata' if possible. But 119da0c48c4Sopenharmony_ci this function can fail if the data was constructed by the 120da0c48c4Sopenharmony_ci program. In this case we have to use 'elf_getdata' and 121da0c48c4Sopenharmony_ci eventually convert the data to the external format. */ 122da0c48c4Sopenharmony_ci data = INTUSE(elf_rawdata) (scn, NULL); 123da0c48c4Sopenharmony_ci if (data != NULL) 124da0c48c4Sopenharmony_ci { 125da0c48c4Sopenharmony_ci /* The raw data is available. */ 126da0c48c4Sopenharmony_ci result = process_block (result, data); 127da0c48c4Sopenharmony_ci 128da0c48c4Sopenharmony_ci /* Maybe the user added more data. These blocks cannot be 129da0c48c4Sopenharmony_ci read using 'elf_rawdata'. Simply proceed with looking 130da0c48c4Sopenharmony_ci for more data block with 'elf_getdata'. */ 131da0c48c4Sopenharmony_ci } 132da0c48c4Sopenharmony_ci 133da0c48c4Sopenharmony_ci /* Iterate through the list of data blocks. */ 134da0c48c4Sopenharmony_ci while ((data = INTUSE(elf_getdata) (scn, data)) != NULL) 135da0c48c4Sopenharmony_ci /* If the file byte order is the same as the host byte order 136da0c48c4Sopenharmony_ci process the buffer directly. If the data is just a stream 137da0c48c4Sopenharmony_ci of bytes which the library will not convert we can use it 138da0c48c4Sopenharmony_ci as well. */ 139da0c48c4Sopenharmony_ci if (likely (same_byte_order) || data->d_type == ELF_T_BYTE) 140da0c48c4Sopenharmony_ci result = process_block (result, data); 141da0c48c4Sopenharmony_ci else 142da0c48c4Sopenharmony_ci { 143da0c48c4Sopenharmony_ci /* Convert the data to file byte order. */ 144da0c48c4Sopenharmony_ci if (INTUSE(elfw2(LIBELFBITS,xlatetof)) (data, data, ident[EI_DATA]) 145da0c48c4Sopenharmony_ci == NULL) 146da0c48c4Sopenharmony_ci { 147da0c48c4Sopenharmony_ci result = -1l; 148da0c48c4Sopenharmony_ci goto out; 149da0c48c4Sopenharmony_ci } 150da0c48c4Sopenharmony_ci 151da0c48c4Sopenharmony_ci result = process_block (result, data); 152da0c48c4Sopenharmony_ci 153da0c48c4Sopenharmony_ci /* And convert it back. */ 154da0c48c4Sopenharmony_ci if (INTUSE(elfw2(LIBELFBITS,xlatetom)) (data, data, ident[EI_DATA]) 155da0c48c4Sopenharmony_ci == NULL) 156da0c48c4Sopenharmony_ci { 157da0c48c4Sopenharmony_ci result = -1l; 158da0c48c4Sopenharmony_ci goto out; 159da0c48c4Sopenharmony_ci } 160da0c48c4Sopenharmony_ci } 161da0c48c4Sopenharmony_ci } 162da0c48c4Sopenharmony_ci 163da0c48c4Sopenharmony_ci out: 164da0c48c4Sopenharmony_ci rwlock_unlock (elf->lock); 165da0c48c4Sopenharmony_ci return result; 166da0c48c4Sopenharmony_ci} 167da0c48c4Sopenharmony_ciINTDEF(elfw2(LIBELFBITS,checksum)) 168