1 /* Test program for elf_newdata function.
2 Copyright (C) 2015 Red Hat, Inc.
3 This file is part of elfutils.
4
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 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
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <inttypes.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include "system.h"
30
31 #include ELFUTILS_HEADER(elf)
32 #include <gelf.h>
33
34 // Random data string (16 bytes).
35 static char *DATA = "123456789ABCDEF";
36 static size_t DATA_LEN = 16;
37
38 static void
add_section_data(Elf * elf,char * buf,size_t len)39 add_section_data (Elf *elf, char *buf, size_t len)
40 {
41 printf ("Adding %zd bytes.\n", len);
42
43 Elf_Scn *scn = elf_getscn (elf, 1);
44 if (scn == NULL)
45 {
46 printf ("couldn't get data section: %s\n", elf_errmsg (-1));
47 exit (1);
48 }
49
50 Elf_Data *data = elf_newdata (scn);
51 if (data == NULL)
52 {
53 printf ("cannot create newdata for section: %s\n", elf_errmsg (-1));
54 exit (1);
55 }
56
57 data->d_buf = buf;
58 data->d_type = ELF_T_BYTE;
59 data->d_size = len;
60 data->d_align = 1;
61 data->d_version = EV_CURRENT;
62
63 // Let the library compute the internal structure information.
64 if (elf_update (elf, ELF_C_NULL) < 0)
65 {
66 printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1));
67 exit (1);
68 }
69
70 }
71
72 static Elf *
create_elf(int fd,int class,int use_mmap)73 create_elf (int fd, int class, int use_mmap)
74 {
75 Elf *elf = elf_begin (fd, use_mmap ? ELF_C_WRITE_MMAP : ELF_C_WRITE, NULL);
76 if (elf == NULL)
77 {
78 printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
79 exit (1);
80 }
81
82 // Create an ELF header.
83 if (gelf_newehdr (elf, class) == 0)
84 {
85 printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
86 exit (1);
87 }
88
89 GElf_Ehdr ehdr_mem;
90 GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
91 if (ehdr == NULL)
92 {
93 printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
94 exit (1);
95 }
96
97 // Initialize header.
98 ehdr->e_ident[EI_DATA] = class == ELFCLASS32 ? ELFDATA2LSB : ELFDATA2MSB;
99 ehdr->e_ident[EI_OSABI] = ELFOSABI_GNU;
100 ehdr->e_type = ET_NONE;
101 ehdr->e_machine = class == ELFCLASS32 ? EM_PPC : EM_X86_64;
102 ehdr->e_version = EV_CURRENT;
103
104 // Update the ELF header.
105 if (gelf_update_ehdr (elf, ehdr) == 0)
106 {
107 printf ("cannot update ELF header: %s\n", elf_errmsg (-1));
108 exit (1);
109 }
110
111 // Create a section.
112 Elf_Scn *scn = elf_newscn (elf);
113 if (scn == NULL)
114 {
115 printf ("cannot create new section: %s\n", elf_errmsg (-1));
116 exit (1);
117 }
118
119 GElf_Shdr shdr_mem;
120 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
121 if (shdr == NULL)
122 {
123 printf ("cannot get header for data section: %s\n", elf_errmsg (-1));
124 exit (1);
125 }
126
127 shdr->sh_type = SHT_PROGBITS;
128 shdr->sh_flags = 0;
129 shdr->sh_addr = 0;
130 shdr->sh_link = SHN_UNDEF;
131 shdr->sh_info = SHN_UNDEF;
132 shdr->sh_addralign = 1;
133 shdr->sh_entsize = 1;
134 shdr->sh_name = 0;
135
136 // Finish section, update the header.
137 if (gelf_update_shdr (scn, shdr) == 0)
138 {
139 printf ("cannot update header for DATA section: %s\n", elf_errmsg (-1));
140 exit (1);
141 }
142
143 // Add some data to the section.
144 add_section_data (elf, DATA, DATA_LEN);
145
146 // Write everything to disk.
147 if (elf_update (elf, ELF_C_WRITE) < 0)
148 {
149 printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
150 exit (1);
151 }
152
153 return elf;
154 }
155
156 static Elf *
read_elf(int fd,int use_mmap)157 read_elf (int fd, int use_mmap)
158 {
159 printf ("Reading ELF file\n");
160 Elf *elf = elf_begin (fd, use_mmap ? ELF_C_RDWR_MMAP : ELF_C_RDWR, NULL);
161 if (elf == NULL)
162 {
163 printf ("cannot create ELF descriptor read-again: %s\n", elf_errmsg (-1));
164 exit (1);
165 }
166
167 return elf;
168 }
169
170 static void
check_section_size(Elf * elf,size_t size)171 check_section_size (Elf *elf, size_t size)
172 {
173 Elf_Scn *scn = elf_getscn (elf, 1);
174 if (scn == NULL)
175 {
176 printf ("couldn't get data section: %s\n", elf_errmsg (-1));
177 exit (1);
178 }
179
180 GElf_Shdr shdr_mem;
181 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
182 if (shdr == NULL)
183 {
184 printf ("cannot get header for DATA section: %s\n", elf_errmsg (-1));
185 exit (1);
186 }
187
188 if (shdr->sh_size == size)
189 printf ("OK %zd bytes.\n", size);
190 else
191 {
192 printf ("BAD size, expected %zd, got %" PRIu64 "\n",
193 size, shdr->sh_size);
194 exit (-1);
195 }
196 }
197
198 static void
check_section_data(Elf * elf,char * data,size_t len,size_t times)199 check_section_data (Elf *elf, char *data, size_t len, size_t times)
200 {
201 Elf_Scn *scn = elf_getscn (elf, 1);
202 if (scn == NULL)
203 {
204 printf ("couldn't get data section: %s\n", elf_errmsg (-1));
205 exit (1);
206 }
207
208 Elf_Data *d = NULL;
209 for (size_t i = 0; i < times; i++)
210 {
211 if (d == NULL || i * len >= d->d_off + d->d_size)
212 {
213 d = elf_getdata (scn, d);
214 if (d == NULL)
215 {
216 printf ("cannot get data for section item %zd: %s\n",
217 i, elf_errmsg (-1));
218 exit (1);
219 }
220 else
221 printf ("OK, section data item %zd (d_off: %" PRId64
222 ", d_size: %zd)\n", i, d->d_off, d->d_size);
223 }
224 char *d_data = (char *) d->d_buf + (len * i) - d->d_off;
225 printf ("%zd data (d_off: %" PRId64
226 ", len * i: %zd): (%p + %" PRId64 ") %s\n",
227 i, d->d_off, len * i, d->d_buf, (len * i) - d->d_off, d_data);
228 if (memcmp (data, d_data, len) != 0)
229 {
230 printf ("Got bad data in section for item %zd.\n", i);
231 exit (1);
232 }
233 }
234 }
235
236 static void
check_elf(int class,int use_mmap)237 check_elf (int class, int use_mmap)
238 {
239 static const char *fname;
240 if (class == ELFCLASS32)
241 fname = use_mmap ? "newdata.elf32.mmap" : "newdata.elf32";
242 else
243 fname = use_mmap ? "newdata.elf64.mmap" : "newdata.elf64";
244
245 printf ("\ncheck_elf: %s\n", fname);
246
247 int fd = open (fname, O_RDWR|O_CREAT|O_TRUNC, DEFFILEMODE);
248 if (fd == -1)
249 {
250 printf ("cannot create `%s': %s\n", fname, strerror (errno));
251 exit (1);
252 }
253
254 Elf *elf = create_elf (fd, class, use_mmap);
255 check_section_size (elf, DATA_LEN);
256 check_section_data (elf, DATA, DATA_LEN, 1);
257
258 // Add some more data (won't be written to disk).
259 add_section_data (elf, DATA, DATA_LEN);
260 check_section_size (elf, 2 * DATA_LEN);
261 check_section_data (elf, DATA, DATA_LEN, 2);
262
263 if (elf_end (elf) != 0)
264 {
265 printf ("failure in elf_end: %s\n", elf_errmsg (-1));
266 exit (1);
267 }
268
269 close (fd);
270
271 // Read the ELF from disk now. And add new data directly.
272 fd = open (fname, O_RDONLY);
273 if (fd == -1)
274 {
275 printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
276 exit (1);
277 }
278
279 elf = read_elf (fd, use_mmap);
280 check_section_size (elf, DATA_LEN);
281 // But don't check contents, that would read the data...
282
283 // Add some more data.
284 add_section_data (elf, DATA, DATA_LEN);
285 check_section_size (elf, 2 * DATA_LEN);
286 check_section_data (elf, DATA, DATA_LEN, 2);
287
288 // And some more.
289 add_section_data (elf, DATA, DATA_LEN);
290 check_section_size (elf, 3 * DATA_LEN);
291 check_section_data (elf, DATA, DATA_LEN, 3);
292
293 if (elf_end (elf) != 0)
294 {
295 printf ("failure in elf_end: %s\n", elf_errmsg (-1));
296 exit (1);
297 }
298
299 close (fd);
300
301 // Read the ELF from disk now. And add new data after raw reading.
302 fd = open (fname, O_RDONLY);
303 if (fd == -1)
304 {
305 printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
306 exit (1);
307 }
308
309 elf = read_elf (fd, use_mmap);
310 check_section_size (elf, DATA_LEN);
311 // But don't check contents, that would read the data...
312
313 // Get raw data before adding new data.
314 Elf_Scn *scn = elf_getscn (elf, 1);
315 if (scn == NULL)
316 {
317 printf ("couldn't get data section: %s\n", elf_errmsg (-1));
318 exit (1);
319 }
320
321 printf ("elf_rawdata\n");
322 Elf_Data *data = elf_rawdata (scn, NULL);
323 if (data == NULL)
324 {
325 printf ("couldn't get raw data from section: %s\n", elf_errmsg (-1));
326 exit (1);
327 }
328
329 if (data->d_size != DATA_LEN)
330 {
331 printf ("Unexpected Elf_Data: %zd", data->d_size);
332 exit (1);
333 }
334
335 // Now add more data.
336 add_section_data (elf, DATA, DATA_LEN);
337 check_section_size (elf, 2 * DATA_LEN);
338 check_section_data (elf, DATA, DATA_LEN, 2);
339
340 // And some more.
341 add_section_data (elf, DATA, DATA_LEN);
342 check_section_size (elf, 3 * DATA_LEN);
343 check_section_data (elf, DATA, DATA_LEN, 3);
344
345 if (elf_end (elf) != 0)
346 {
347 printf ("failure in elf_end: %s\n", elf_errmsg (-1));
348 exit (1);
349 }
350
351 close (fd);
352
353 // Read the ELF from disk now. And add new data after data reading.
354 fd = open (fname, O_RDONLY);
355 if (fd == -1)
356 {
357 printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
358 exit (1);
359 }
360
361 elf = read_elf (fd, use_mmap);
362 check_section_size (elf, DATA_LEN);
363 // Get (converted) data before adding new data.
364 check_section_data (elf, DATA, DATA_LEN, 1);
365
366 printf ("elf_getdata\n");
367
368 // Now add more data.
369 add_section_data (elf, DATA, DATA_LEN);
370 check_section_size (elf, 2 * DATA_LEN);
371 check_section_data (elf, DATA, DATA_LEN, 2);
372
373 // And some more.
374 add_section_data (elf, DATA, DATA_LEN);
375 check_section_size (elf, 3 * DATA_LEN);
376 check_section_data (elf, DATA, DATA_LEN, 3);
377
378 if (elf_end (elf) != 0)
379 {
380 printf ("failure in elf_end: %s\n", elf_errmsg (-1));
381 exit (1);
382 }
383
384 close (fd);
385
386 unlink (fname);
387 }
388
389 int
main(int argc,char * argv[])390 main (int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused)))
391 {
392 // Initialize libelf.
393 elf_version (EV_CURRENT);
394
395 // Fill holes with something non-zero to more easily spot bad data.
396 elf_fill ('X');
397
398 check_elf (ELFCLASS32, 0);
399 check_elf (ELFCLASS32, 1);
400 check_elf (ELFCLASS64, 0);
401 check_elf (ELFCLASS64, 1);
402
403 return 0;
404 }
405