1 /* Test program for elf_update function.
2    Copyright (C) 2000, 2001, 2002, 2005 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 
31 #include ELFUTILS_HEADER(ebl)
32 
33 
34 int
35 main (int argc, char *argv[] __attribute__ ((unused)))
36 {
37   const char fname[] = "xxx_update4";
38   int fd;
39   Elf *elf;
40   Elf32_Ehdr *ehdr;
41   Elf32_Phdr *phdr;
42   Elf_Scn *scn;
43   Elf32_Shdr *shdr;
44   Elf_Data *data;
45   struct Ebl_Strtab *shst;
46   struct Ebl_Strent *firstse;
47   struct Ebl_Strent *secondse;
48   struct Ebl_Strent *thirdse;
49   struct Ebl_Strent *fourthse;
50   struct Ebl_Strent *shstrtabse;
51   int i;
52 
53   fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, 0666);
54   if (fd == -1)
55     {
56       printf ("cannot open `%s': %s\n", fname, strerror (errno));
57       exit (1);
58     }
59 
60   elf_version (EV_CURRENT);
61 
62   elf_fill (0x42);
63 
64   elf = elf_begin (fd, ELF_C_WRITE, NULL);
65   if (elf == NULL)
66     {
67       printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
68       exit (1);
69     }
70 
71   /* Create an ELF header.  */
72   ehdr = elf32_newehdr (elf);
73   if (ehdr == NULL)
74     {
75       printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
76       exit (1);
77     }
78 
79   /* Print the ELF header values.  */
80   if (argc > 1)
81     {
82       for (i = 0; i < EI_NIDENT; ++i)
83 	printf (" %02x", ehdr->e_ident[i]);
84       printf ("\
85 \ntype = %hu\nmachine = %hu\nversion = %u\nentry = %u\nphoff = %u\n"
86 	      "shoff = %u\nflags = %u\nehsize = %hu\nphentsize = %hu\n"
87 	      "phnum = %hu\nshentsize = %hu\nshnum = %hu\nshstrndx = %hu\n",
88 	      ehdr->e_type, ehdr->e_machine, ehdr->e_version, ehdr->e_entry,
89 	      ehdr->e_phoff, ehdr->e_shoff, ehdr->e_flags, ehdr->e_ehsize,
90 	      ehdr->e_phentsize, ehdr->e_phnum, ehdr->e_shentsize,
91 	      ehdr->e_shnum, ehdr->e_shstrndx);
92     }
93 
94   ehdr->e_ident[0] = 42;
95   ehdr->e_ident[4] = 1;
96   ehdr->e_ident[5] = 1;
97   ehdr->e_ident[6] = 2;
98   ehdr->e_type = ET_EXEC;
99   ehdr->e_version = 1;
100   ehdr->e_ehsize = 1;
101   elf_flagehdr (elf, ELF_C_SET, ELF_F_DIRTY);
102 
103   /* Create the program header.  */
104   phdr = elf32_newphdr (elf, 1);
105   if (phdr == NULL)
106     {
107       printf ("cannot create program header: %s\n", elf_errmsg (-1));
108       exit (1);
109     }
110 
111   phdr[0].p_type = PT_PHDR;
112   elf_flagphdr (elf, ELF_C_SET, ELF_F_DIRTY);
113 
114   shst = ebl_strtabinit (true);
115 
116   scn = elf_newscn (elf);
117   if (scn == NULL)
118     {
119       printf ("cannot create first section: %s\n", elf_errmsg (-1));
120       exit (1);
121     }
122   shdr = elf32_getshdr (scn);
123   if (shdr == NULL)
124     {
125       printf ("cannot get header for first section: %s\n", elf_errmsg (-1));
126       exit (1);
127     }
128 
129   firstse = ebl_strtabadd (shst, ".first", 0);
130 
131   shdr->sh_type = SHT_PROGBITS;
132   shdr->sh_flags = SHF_ALLOC | SHF_EXECINSTR;
133   shdr->sh_addr = 0;
134   shdr->sh_link = 0;
135   shdr->sh_info = 0;
136   shdr->sh_entsize = 1;
137 
138   data = elf_newdata (scn);
139   if (data == NULL)
140     {
141       printf ("cannot create data first section: %s\n", elf_errmsg (-1));
142       exit (1);
143     }
144 
145   data->d_buf = "hello";
146   data->d_type = ELF_T_BYTE;
147   data->d_version = EV_CURRENT;
148   data->d_size = 5;
149   data->d_align = 16;
150 
151 
152   scn = elf_newscn (elf);
153   if (scn == NULL)
154     {
155       printf ("cannot create second section: %s\n", elf_errmsg (-1));
156       exit (1);
157     }
158   shdr = elf32_getshdr (scn);
159   if (shdr == NULL)
160     {
161       printf ("cannot get header for second section: %s\n", elf_errmsg (-1));
162       exit (1);
163     }
164 
165   secondse = ebl_strtabadd (shst, ".second", 0);
166 
167   shdr->sh_type = SHT_PROGBITS;
168   shdr->sh_flags = SHF_ALLOC | SHF_WRITE;
169   shdr->sh_addr = 0;
170   shdr->sh_link = 0;
171   shdr->sh_info = 0;
172   shdr->sh_entsize = 1;
173 
174   data = elf_newdata (scn);
175   if (data == NULL)
176     {
177       printf ("cannot create data second section: %s\n", elf_errmsg (-1));
178       exit (1);
179     }
180 
181   data->d_buf = "world";
182   data->d_type = ELF_T_BYTE;
183   data->d_version = EV_CURRENT;
184   data->d_size = 5;
185   data->d_align = 16;
186 
187 
188   scn = elf_newscn (elf);
189   if (scn == NULL)
190     {
191       printf ("cannot create third section: %s\n", elf_errmsg (-1));
192       exit (1);
193     }
194   shdr = elf32_getshdr (scn);
195   if (shdr == NULL)
196     {
197       printf ("cannot get header for third section: %s\n", elf_errmsg (-1));
198       exit (1);
199     }
200 
201   thirdse = ebl_strtabadd (shst, ".third", 0);
202 
203   shdr->sh_type = SHT_PROGBITS;
204   shdr->sh_flags = SHF_ALLOC | SHF_EXECINSTR;
205   shdr->sh_addr = 0;
206   shdr->sh_link = 0;
207   shdr->sh_info = 0;
208   shdr->sh_entsize = 1;
209 
210   data = elf_newdata (scn);
211   if (data == NULL)
212     {
213       printf ("cannot create data third section: %s\n", elf_errmsg (-1));
214       exit (1);
215     }
216 
217   data->d_buf = "!!!!!";
218   data->d_type = ELF_T_BYTE;
219   data->d_version = EV_CURRENT;
220   data->d_size = 5;
221   data->d_align = 16;
222 
223 
224   scn = elf_newscn (elf);
225   if (scn == NULL)
226     {
227       printf ("cannot create fourth section: %s\n", elf_errmsg (-1));
228       exit (1);
229     }
230   shdr = elf32_getshdr (scn);
231   if (shdr == NULL)
232     {
233       printf ("cannot get header for fourth section: %s\n", elf_errmsg (-1));
234       exit (1);
235     }
236 
237   fourthse = ebl_strtabadd (shst, ".fourth", 0);
238 
239   shdr->sh_type = SHT_NOBITS;
240   shdr->sh_flags = SHF_ALLOC | SHF_EXECINSTR;
241   shdr->sh_addr = 0;
242   shdr->sh_link = 0;
243   shdr->sh_info = 0;
244   shdr->sh_entsize = 1;
245   shdr->sh_size = 100;
246 
247   data = elf_newdata (scn);
248   if (data == NULL)
249     {
250       printf ("cannot create data fourth section: %s\n", elf_errmsg (-1));
251       exit (1);
252     }
253 
254   data->d_buf = NULL;
255   data->d_type = ELF_T_BYTE;
256   data->d_version = EV_CURRENT;
257   data->d_size = 100;
258   data->d_align = 16;
259 
260 
261   scn = elf_newscn (elf);
262   if (scn == NULL)
263     {
264       printf ("cannot create SHSTRTAB section: %s\n", elf_errmsg (-1));
265       exit (1);
266     }
267   shdr = elf32_getshdr (scn);
268   if (shdr == NULL)
269     {
270       printf ("cannot get header for SHSTRTAB section: %s\n", elf_errmsg (-1));
271       exit (1);
272     }
273 
274   shstrtabse = ebl_strtabadd (shst, ".shstrtab", 0);
275 
276   shdr->sh_type = SHT_STRTAB;
277   shdr->sh_flags = 0;
278   shdr->sh_addr = 0;
279   shdr->sh_link = SHN_UNDEF;
280   shdr->sh_info = SHN_UNDEF;
281   shdr->sh_entsize = 1;
282 
283   /* We have to store the section index in the ELF header.  */
284   ehdr->e_shstrndx = elf_ndxscn (scn);
285 
286   data = elf_newdata (scn);
287   if (data == NULL)
288     {
289       printf ("cannot create data SHSTRTAB section: %s\n", elf_errmsg (-1));
290       exit (1);
291     }
292 
293   /* No more sections, finalize the section header string table.  */
294   ebl_strtabfinalize (shst, data);
295 
296   elf32_getshdr (elf_getscn (elf, 1))->sh_name = ebl_strtaboffset (firstse);
297   elf32_getshdr (elf_getscn (elf, 2))->sh_name = ebl_strtaboffset (secondse);
298   elf32_getshdr (elf_getscn (elf, 3))->sh_name = ebl_strtaboffset (thirdse);
299   elf32_getshdr (elf_getscn (elf, 4))->sh_name = ebl_strtaboffset (fourthse);
300   shdr->sh_name = ebl_strtaboffset (shstrtabse);
301 
302   /* Let the library compute the internal structure information.  */
303   if (elf_update (elf, ELF_C_NULL) < 0)
304     {
305       printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1));
306       exit (1);
307     }
308 
309   ehdr = elf32_getehdr (elf);
310 
311   phdr[0].p_offset = ehdr->e_phoff;
312   phdr[0].p_offset = ehdr->e_phoff;
313   phdr[0].p_vaddr = ehdr->e_phoff;
314   phdr[0].p_paddr = ehdr->e_phoff;
315   phdr[0].p_flags = PF_R | PF_X;
316   phdr[0].p_filesz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT);
317   phdr[0].p_memsz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT);
318   phdr[0].p_align = sizeof (Elf32_Word);
319 
320   /* Write out the file.  */
321   if (elf_update (elf, ELF_C_WRITE) < 0)
322     {
323       printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
324       exit (1);
325     }
326 
327   /* We don't need the string table anymore.  */
328   ebl_strtabfree (shst);
329 
330   /* And the data allocated in the .shstrtab section.  */
331   free (data->d_buf);
332 
333   /* Print the ELF header values.  */
334   if (argc > 1)
335     {
336       for (i = 0; i < EI_NIDENT; ++i)
337 	printf (" %02x", ehdr->e_ident[i]);
338       printf ("\
339 \ntype = %hu\nmachine = %hu\nversion = %u\nentry = %u\nphoff = %u\n"
340 	      "shoff = %u\nflags = %u\nehsize = %hu\nphentsize = %hu\n"
341 	      "phnum = %hu\nshentsize = %hu\nshnum = %hu\nshstrndx = %hu\n",
342 	      ehdr->e_type, ehdr->e_machine, ehdr->e_version, ehdr->e_entry,
343 	      ehdr->e_phoff, ehdr->e_shoff, ehdr->e_flags, ehdr->e_ehsize,
344 	      ehdr->e_phentsize, ehdr->e_phnum, ehdr->e_shentsize,
345 	      ehdr->e_shnum, ehdr->e_shstrndx);
346     }
347 
348   if (elf_end (elf) != 0)
349     {
350       printf ("failure in elf_end: %s\n", elf_errmsg (-1));
351       exit (1);
352     }
353 
354   unlink (fname);
355 
356   return 0;
357 }
358