xref: /third_party/elfutils/tests/update4.c (revision da0c48c4)
1/* Test program for elf_update function.
2   Copyright (C) 2000, 2001, 2002, 2005, 2016 Red Hat, Inc.
3   This file is part of elfutils.
4   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
5
6   This file is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 3 of the License, or
9   (at your option) any later version.
10
11   elfutils is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18
19#ifdef HAVE_CONFIG_H
20# include <config.h>
21#endif
22
23#include <errno.h>
24#include <fcntl.h>
25#include <libelf.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <unistd.h>
30#include "system.h"
31
32#include ELFUTILS_HEADER(dwelf)
33
34
35int
36main (int argc, char *argv[] __attribute__ ((unused)))
37{
38  const char fname[] = "xxx_update4";
39  int fd;
40  Elf *elf;
41  Elf32_Ehdr *ehdr;
42  Elf32_Phdr *phdr;
43  Elf_Scn *scn;
44  Elf32_Shdr *shdr;
45  Elf_Data *data;
46  Dwelf_Strtab *shst;
47  Dwelf_Strent *firstse;
48  Dwelf_Strent *secondse;
49  Dwelf_Strent *thirdse;
50  Dwelf_Strent *fourthse;
51  Dwelf_Strent *shstrtabse;
52  int i;
53
54  fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
55  if (fd == -1)
56    {
57      printf ("cannot open `%s': %s\n", fname, strerror (errno));
58      exit (1);
59    }
60
61  elf_version (EV_CURRENT);
62
63  elf_fill (0x42);
64
65  elf = elf_begin (fd, ELF_C_WRITE, NULL);
66  if (elf == NULL)
67    {
68      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
69      exit (1);
70    }
71
72  /* Create an ELF header.  */
73  ehdr = elf32_newehdr (elf);
74  if (ehdr == NULL)
75    {
76      printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
77      exit (1);
78    }
79
80  /* Print the ELF header values.  */
81  if (argc > 1)
82    {
83      for (i = 0; i < EI_NIDENT; ++i)
84	printf (" %02x", ehdr->e_ident[i]);
85      printf ("\
86\ntype = %hu\nmachine = %hu\nversion = %u\nentry = %u\nphoff = %u\n"
87	      "shoff = %u\nflags = %u\nehsize = %hu\nphentsize = %hu\n"
88	      "phnum = %hu\nshentsize = %hu\nshnum = %hu\nshstrndx = %hu\n",
89	      ehdr->e_type, ehdr->e_machine, ehdr->e_version, ehdr->e_entry,
90	      ehdr->e_phoff, ehdr->e_shoff, ehdr->e_flags, ehdr->e_ehsize,
91	      ehdr->e_phentsize, ehdr->e_phnum, ehdr->e_shentsize,
92	      ehdr->e_shnum, ehdr->e_shstrndx);
93    }
94
95  ehdr->e_ident[0] = 42;
96  ehdr->e_ident[4] = 1;
97  ehdr->e_ident[5] = 1;
98  ehdr->e_ident[6] = 2;
99  ehdr->e_type = ET_EXEC;
100  ehdr->e_version = 1;
101  ehdr->e_ehsize = 1;
102  elf_flagehdr (elf, ELF_C_SET, ELF_F_DIRTY);
103
104  /* Create the program header.  */
105  phdr = elf32_newphdr (elf, 1);
106  if (phdr == NULL)
107    {
108      printf ("cannot create program header: %s\n", elf_errmsg (-1));
109      exit (1);
110    }
111
112  phdr[0].p_type = PT_PHDR;
113  elf_flagphdr (elf, ELF_C_SET, ELF_F_DIRTY);
114
115  shst = dwelf_strtab_init (true);
116
117  scn = elf_newscn (elf);
118  if (scn == NULL)
119    {
120      printf ("cannot create first section: %s\n", elf_errmsg (-1));
121      exit (1);
122    }
123  shdr = elf32_getshdr (scn);
124  if (shdr == NULL)
125    {
126      printf ("cannot get header for first section: %s\n", elf_errmsg (-1));
127      exit (1);
128    }
129
130  firstse = dwelf_strtab_add (shst, ".first");
131
132  shdr->sh_type = SHT_PROGBITS;
133  shdr->sh_flags = SHF_ALLOC | SHF_EXECINSTR;
134  shdr->sh_addr = 0;
135  shdr->sh_link = 0;
136  shdr->sh_info = 0;
137  shdr->sh_entsize = 1;
138
139  data = elf_newdata (scn);
140  if (data == NULL)
141    {
142      printf ("cannot create data first section: %s\n", elf_errmsg (-1));
143      exit (1);
144    }
145
146  data->d_buf = "hello";
147  data->d_type = ELF_T_BYTE;
148  data->d_version = EV_CURRENT;
149  data->d_size = 5;
150  data->d_align = 16;
151
152
153  scn = elf_newscn (elf);
154  if (scn == NULL)
155    {
156      printf ("cannot create second section: %s\n", elf_errmsg (-1));
157      exit (1);
158    }
159  shdr = elf32_getshdr (scn);
160  if (shdr == NULL)
161    {
162      printf ("cannot get header for second section: %s\n", elf_errmsg (-1));
163      exit (1);
164    }
165
166  secondse = dwelf_strtab_add (shst, ".second");
167
168  shdr->sh_type = SHT_PROGBITS;
169  shdr->sh_flags = SHF_ALLOC | SHF_WRITE;
170  shdr->sh_addr = 0;
171  shdr->sh_link = 0;
172  shdr->sh_info = 0;
173  shdr->sh_entsize = 1;
174
175  data = elf_newdata (scn);
176  if (data == NULL)
177    {
178      printf ("cannot create data second section: %s\n", elf_errmsg (-1));
179      exit (1);
180    }
181
182  data->d_buf = "world";
183  data->d_type = ELF_T_BYTE;
184  data->d_version = EV_CURRENT;
185  data->d_size = 5;
186  data->d_align = 16;
187
188
189  scn = elf_newscn (elf);
190  if (scn == NULL)
191    {
192      printf ("cannot create third section: %s\n", elf_errmsg (-1));
193      exit (1);
194    }
195  shdr = elf32_getshdr (scn);
196  if (shdr == NULL)
197    {
198      printf ("cannot get header for third section: %s\n", elf_errmsg (-1));
199      exit (1);
200    }
201
202  thirdse = dwelf_strtab_add (shst, ".third");
203
204  shdr->sh_type = SHT_PROGBITS;
205  shdr->sh_flags = SHF_ALLOC | SHF_EXECINSTR;
206  shdr->sh_addr = 0;
207  shdr->sh_link = 0;
208  shdr->sh_info = 0;
209  shdr->sh_entsize = 1;
210
211  data = elf_newdata (scn);
212  if (data == NULL)
213    {
214      printf ("cannot create data third section: %s\n", elf_errmsg (-1));
215      exit (1);
216    }
217
218  data->d_buf = "!!!!!";
219  data->d_type = ELF_T_BYTE;
220  data->d_version = EV_CURRENT;
221  data->d_size = 5;
222  data->d_align = 16;
223
224
225  scn = elf_newscn (elf);
226  if (scn == NULL)
227    {
228      printf ("cannot create fourth section: %s\n", elf_errmsg (-1));
229      exit (1);
230    }
231  shdr = elf32_getshdr (scn);
232  if (shdr == NULL)
233    {
234      printf ("cannot get header for fourth section: %s\n", elf_errmsg (-1));
235      exit (1);
236    }
237
238  fourthse = dwelf_strtab_add (shst, ".fourth");
239
240  shdr->sh_type = SHT_NOBITS;
241  shdr->sh_flags = SHF_ALLOC | SHF_EXECINSTR;
242  shdr->sh_addr = 0;
243  shdr->sh_link = 0;
244  shdr->sh_info = 0;
245  shdr->sh_entsize = 1;
246  shdr->sh_size = 100;
247
248  data = elf_newdata (scn);
249  if (data == NULL)
250    {
251      printf ("cannot create data fourth section: %s\n", elf_errmsg (-1));
252      exit (1);
253    }
254
255  data->d_buf = NULL;
256  data->d_type = ELF_T_BYTE;
257  data->d_version = EV_CURRENT;
258  data->d_size = 100;
259  data->d_align = 16;
260
261
262  scn = elf_newscn (elf);
263  if (scn == NULL)
264    {
265      printf ("cannot create SHSTRTAB section: %s\n", elf_errmsg (-1));
266      exit (1);
267    }
268  shdr = elf32_getshdr (scn);
269  if (shdr == NULL)
270    {
271      printf ("cannot get header for SHSTRTAB section: %s\n", elf_errmsg (-1));
272      exit (1);
273    }
274
275  shstrtabse = dwelf_strtab_add (shst, ".shstrtab");
276
277  shdr->sh_type = SHT_STRTAB;
278  shdr->sh_flags = 0;
279  shdr->sh_addr = 0;
280  shdr->sh_link = SHN_UNDEF;
281  shdr->sh_info = SHN_UNDEF;
282  shdr->sh_entsize = 1;
283
284  /* We have to store the section index in the ELF header.  */
285  ehdr->e_shstrndx = elf_ndxscn (scn);
286
287  data = elf_newdata (scn);
288  if (data == NULL)
289    {
290      printf ("cannot create data SHSTRTAB section: %s\n", elf_errmsg (-1));
291      exit (1);
292    }
293
294  /* No more sections, finalize the section header string table.  */
295  dwelf_strtab_finalize (shst, data);
296
297  elf32_getshdr (elf_getscn (elf, 1))->sh_name = dwelf_strent_off (firstse);
298  elf32_getshdr (elf_getscn (elf, 2))->sh_name = dwelf_strent_off (secondse);
299  elf32_getshdr (elf_getscn (elf, 3))->sh_name = dwelf_strent_off (thirdse);
300  elf32_getshdr (elf_getscn (elf, 4))->sh_name = dwelf_strent_off (fourthse);
301  shdr->sh_name = dwelf_strent_off (shstrtabse);
302
303  /* Let the library compute the internal structure information.  */
304  if (elf_update (elf, ELF_C_NULL) < 0)
305    {
306      printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1));
307      exit (1);
308    }
309
310  ehdr = elf32_getehdr (elf);
311
312  phdr[0].p_offset = ehdr->e_phoff;
313  phdr[0].p_offset = ehdr->e_phoff;
314  phdr[0].p_vaddr = ehdr->e_phoff;
315  phdr[0].p_paddr = ehdr->e_phoff;
316  phdr[0].p_flags = PF_R | PF_X;
317  phdr[0].p_filesz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT);
318  phdr[0].p_memsz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT);
319  phdr[0].p_align = sizeof (Elf32_Word);
320
321  /* Write out the file.  */
322  if (elf_update (elf, ELF_C_WRITE) < 0)
323    {
324      printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
325      exit (1);
326    }
327
328  /* We don't need the string table anymore.  */
329  dwelf_strtab_free (shst);
330
331  /* And the data allocated in the .shstrtab section.  */
332  free (data->d_buf);
333
334  /* Print the ELF header values.  */
335  if (argc > 1)
336    {
337      for (i = 0; i < EI_NIDENT; ++i)
338	printf (" %02x", ehdr->e_ident[i]);
339      printf ("\
340\ntype = %hu\nmachine = %hu\nversion = %u\nentry = %u\nphoff = %u\n"
341	      "shoff = %u\nflags = %u\nehsize = %hu\nphentsize = %hu\n"
342	      "phnum = %hu\nshentsize = %hu\nshnum = %hu\nshstrndx = %hu\n",
343	      ehdr->e_type, ehdr->e_machine, ehdr->e_version, ehdr->e_entry,
344	      ehdr->e_phoff, ehdr->e_shoff, ehdr->e_flags, ehdr->e_ehsize,
345	      ehdr->e_phentsize, ehdr->e_phnum, ehdr->e_shentsize,
346	      ehdr->e_shnum, ehdr->e_shstrndx);
347    }
348
349  if (elf_end (elf) != 0)
350    {
351      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
352      exit (1);
353    }
354
355  unlink (fname);
356
357  return 0;
358}
359