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