1 /* Compute simple checksum from permanent parts of the ELF file. 2 Copyright (C) 2002, 2003, 2004, 2005, 2009 Red Hat, Inc. 3 This file is part of Red Hat elfutils. 4 Written by Ulrich Drepper <drepper (at) redhat.com>, 2002. 5 6 Red Hat elfutils is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by the 8 Free Software Foundation; version 2 of the License. 9 10 Red Hat elfutils is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License along 16 with Red Hat elfutils; if not, write to the Free Software Foundation, 17 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 18 19 In addition, as a special exception, Red Hat, Inc. gives You the 20 additional right to link the code of Red Hat elfutils with code licensed 21 under any Open Source Initiative certified open source license 22 (http://www.opensource.org/licenses/index.php) which requires the 23 distribution of source code with any binary distribution and to 24 distribute linked combinations of the two. Non-GPL Code permitted under 25 this exception must only link to the code of Red Hat elfutils through 26 those well defined interfaces identified in the file named EXCEPTION 27 found in the source code files (the "Approved Interfaces"). The files 28 of Non-GPL Code may instantiate templates or use macros or inline 29 functions from the Approved Interfaces without causing the resulting 30 work to be covered by the GNU General Public License. Only Red Hat, 31 Inc. may make changes or additions to the list of Approved Interfaces. 32 Red Hat's grant of this exception is conditioned upon your not adding 33 any new exceptions. If you wish to add a new Approved Interface or 34 exception, please contact Red Hat. You must obey the GNU General Public 35 License in all respects for all of the Red Hat elfutils code and other 36 code used in conjunction with Red Hat elfutils except the Non-GPL Code 37 covered by this exception. If you modify this file, you may extend this 38 exception to your version of the file, but you are not obligated to do 39 so. If you do not wish to provide this exception without modification, 40 you must delete this exception statement from your version and license 41 this file solely under the GPL without exception. 42 43 Red Hat elfutils is an included package of the Open Invention Network. 44 An included package of the Open Invention Network is a package for which 45 Open Invention Network licensees cross-license their patents. No patent 46 license is granted, either expressly or impliedly, by designation as an 47 included package. Should you wish to participate in the Open Invention 48 Network licensing program, please visit www.openinventionnetwork.com 49 <http://www.openinventionnetwork.com>. */ 50 51 #ifdef HAVE_CONFIG_H 52 # include <config.h> 53 #endif 54 55 #include <assert.h> 56 #include <endian.h> 57 #include <stdbool.h> 58 #include <stddef.h> 59 #include <string.h> 60 61 #include "gelf.h" 62 #include "libelfP.h" 63 #include "elf-knowledge.h" 64 65 #ifndef LIBELFBITS 66 # define LIBELFBITS 32 67 #endif 68 69 70 /* The SECTION_STRIP_P macro wants to call into libebl which we cannot 71 do and do not have to do here. Provide a dummy replacement. */ 72 #define ebl_debugscn_p(ebl, name) true 73 74 75 #define process_block(crc, data) \ 76 __libelf_crc32 (crc, data->d_buf, data->d_size) 77 78 79 long int 80 elfw2(LIBELFBITS,checksum) (elf) 81 Elf *elf; 82 { 83 size_t shstrndx; 84 Elf_Scn *scn; 85 long int result = 0; 86 unsigned char *ident; 87 bool same_byte_order; 88 89 if (elf == NULL) 90 return -1l; 91 92 /* Find the section header string table. */ 93 if (INTUSE(elf_getshdrstrndx) (elf, &shstrndx) < 0) 94 { 95 /* This can only happen if the ELF handle is not for real. */ 96 __libelf_seterrno (ELF_E_INVALID_HANDLE); 97 return -1l; 98 } 99 100 /* Determine whether the byte order of the file and that of the host 101 is the same. */ 102 ident = elf->state.ELFW(elf,LIBELFBITS).ehdr->e_ident; 103 same_byte_order = ((ident[EI_DATA] == ELFDATA2LSB 104 && __BYTE_ORDER == __LITTLE_ENDIAN) 105 || (ident[EI_DATA] == ELFDATA2MSB 106 && __BYTE_ORDER == __BIG_ENDIAN)); 107 108 /* If we don't have native byte order, we will likely need to 109 convert the data with xlate functions. We do it upfront instead 110 of relocking mid-iteration. */ 111 if (!likely (same_byte_order)) 112 rwlock_wrlock (elf->lock); 113 else 114 rwlock_rdlock (elf->lock); 115 116 /* Iterate over all sections to find those which are not strippable. */ 117 scn = NULL; 118 while ((scn = INTUSE(elf_nextscn) (elf, scn)) != NULL) 119 { 120 GElf_Shdr shdr_mem; 121 GElf_Shdr *shdr; 122 Elf_Data *data; 123 124 /* Get the section header. */ 125 shdr = INTUSE(gelf_getshdr) (scn, &shdr_mem); 126 if (shdr == NULL) 127 { 128 __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER); 129 result = -1l; 130 goto out; 131 } 132 133 if (SECTION_STRIP_P (shdr, 134 INTUSE(elf_strptr) (elf, shstrndx, shdr->sh_name), 135 true)) 136 /* The section can be stripped. Don't use it. */ 137 continue; 138 139 /* Do not look at NOBITS sections. */ 140 if (shdr->sh_type == SHT_NOBITS) 141 continue; 142 143 /* To compute the checksum we need to get to the data. For 144 repeatable results we must use the external format. The data 145 we get with 'elf'getdata' might be changed for endianess 146 reasons. Therefore we use 'elf_rawdata' if possible. But 147 this function can fail if the data was constructed by the 148 program. In this case we have to use 'elf_getdata' and 149 eventually convert the data to the external format. */ 150 data = INTUSE(elf_rawdata) (scn, NULL); 151 if (data != NULL) 152 { 153 /* The raw data is available. */ 154 result = process_block (result, data); 155 156 /* Maybe the user added more data. These blocks cannot be 157 read using 'elf_rawdata'. Simply proceed with looking 158 for more data block with 'elf_getdata'. */ 159 } 160 161 /* Iterate through the list of data blocks. */ 162 while ((data = INTUSE(elf_getdata) (scn, data)) != NULL) 163 /* If the file byte order is the same as the host byte order 164 process the buffer directly. If the data is just a stream 165 of bytes which the library will not convert we can use it 166 as well. */ 167 if (likely (same_byte_order) || data->d_type == ELF_T_BYTE) 168 result = process_block (result, data); 169 else 170 { 171 /* Convert the data to file byte order. */ 172 if (INTUSE(elfw2(LIBELFBITS,xlatetof)) (data, data, ident[EI_DATA]) 173 == NULL) 174 { 175 result = -1l; 176 goto out; 177 } 178 179 result = process_block (result, data); 180 181 /* And convert it back. */ 182 if (INTUSE(elfw2(LIBELFBITS,xlatetom)) (data, data, ident[EI_DATA]) 183 == NULL) 184 { 185 result = -1l; 186 goto out; 187 } 188 } 189 } 190 191 out: 192 rwlock_unlock (elf->lock); 193 return result; 194 } 195 INTDEF(elfw2(LIBELFBITS,checksum)) 196