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