3e9f9fe69a3d4c6638f40fe49fd10fa4647b2511
[platform/upstream/elfutils.git] / tests / alldts.c
1 /* Create an ELF file with all the DT_* flags set.
2    Copyright (C) 2011, 2016 Red Hat, Inc.
3    This file is part of elfutils.
4    Written by Marek Polacek <mpolacek@redhat.com>, 2011.
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 ELFUTILS_HEADER(dwelf)
24 #include <elf.h>
25 #include <gelf.h>
26 #include <fcntl.h>
27 #include <libelf.h>
28 #include <stdio.h>
29 #include <stdio_ext.h>
30 #include <stdint.h>
31 #include <stdbool.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include "system.h"
36
37
38 int
39 main (void)
40 {
41   static const char fname[] = "testfile-alldts";
42   Dwelf_Strtab *shst;
43   Dwelf_Strent *dynscn;
44   Dwelf_Strent *shstrtabse;
45   const Elf32_Sword dtflags[] =
46     {
47       DT_NULL, DT_NEEDED, DT_PLTRELSZ, DT_PLTGOT,
48       DT_HASH, DT_STRTAB, DT_SYMTAB, DT_RELA,
49       DT_RELASZ, DT_RELAENT, DT_STRSZ, DT_SYMENT,
50       DT_INIT, DT_FINI, DT_SONAME, DT_RPATH,
51       DT_SYMBOLIC, DT_REL, DT_RELSZ, DT_RELENT,
52       DT_PLTREL, DT_DEBUG, DT_TEXTREL, DT_JMPREL,
53       DT_BIND_NOW, DT_INIT_ARRAY, DT_FINI_ARRAY,
54       DT_INIT_ARRAYSZ, DT_FINI_ARRAYSZ, DT_RUNPATH,
55       DT_FLAGS, DT_ENCODING, DT_PREINIT_ARRAY,
56       DT_PREINIT_ARRAYSZ, DT_VERSYM, DT_GNU_PRELINKED,
57       DT_GNU_CONFLICTSZ, DT_GNU_LIBLISTSZ, DT_CHECKSUM,
58       DT_PLTPADSZ, DT_MOVEENT, DT_MOVESZ, DT_FEATURE_1,
59       DT_POSFLAG_1, DT_SYMINSZ, DT_SYMINENT, DT_GNU_HASH,
60       DT_TLSDESC_PLT, DT_TLSDESC_GOT, DT_GNU_CONFLICT,
61       DT_GNU_LIBLIST, DT_CONFIG, DT_DEPAUDIT, DT_AUDIT,
62       DT_PLTPAD, DT_MOVETAB, DT_SYMINFO, DT_RELACOUNT,
63       DT_RELCOUNT, DT_FLAGS_1, DT_VERDEF, DT_VERDEFNUM,
64       DT_VERNEED, DT_VERNEEDNUM, DT_AUXILIARY, DT_FILTER
65     };
66   const int ndtflags = sizeof (dtflags) / sizeof (dtflags[0]);
67
68   /* We use no threads here which can interfere with handling a stream.  */
69   (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
70
71   /* Open the file.  */
72   int fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
73   if (fd == -1)
74     {
75       printf ("cannot open `%s': %m\n", fname);
76       return 1;
77     }
78
79   /* Tell the library which version are we expecting.  */
80   elf_version (EV_CURRENT);
81
82   /* Create an ELF descriptor.  */
83   Elf *elf = elf_begin (fd, ELF_C_WRITE, NULL);
84   if (elf == NULL)
85     {
86       printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
87       return 1;
88     }
89
90   /* Create an ELF header.  */
91   Elf32_Ehdr *ehdr = elf32_newehdr (elf);
92   if (ehdr == NULL)
93     {
94       printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
95       return 1;
96     }
97
98   ehdr->e_ident[0] = 42;
99   ehdr->e_ident[5] = 1;
100   ehdr->e_ident[6] = 2;
101   ehdr->e_type = ET_EXEC;
102   ehdr->e_machine = EM_386;
103   ehdr->e_version = 1;
104   ehdr->e_ehsize = 1;
105   ehdr->e_shnum = 3;
106
107   elf_flagehdr (elf, ELF_C_SET, ELF_F_DIRTY);
108
109   /* Create the program headers.  */
110   Elf32_Phdr *phdr = elf32_newphdr (elf, 2);
111   if (phdr == NULL)
112     {
113       printf ("cannot create program headers: %s\n", elf_errmsg (-1));
114       return 1;
115     }
116
117   phdr[0].p_type = PT_PHDR;
118   phdr[1].p_type = PT_DYNAMIC;
119
120   elf_flagphdr (elf, ELF_C_SET, ELF_F_DIRTY);
121   shst = dwelf_strtab_init (true);
122
123   /* Create the .dynamic section.  */
124   Elf_Scn *scn = elf_newscn (elf);
125   if (scn == NULL)
126     {
127       printf ("cannot create DYNAMIC section: %s\n", elf_errmsg (-1));
128       return 1;
129     }
130
131   Elf32_Shdr *shdr = elf32_getshdr (scn);
132   if (shdr == NULL)
133     {
134       printf ("cannot get header for DYNAMIC section: %s\n", elf_errmsg (-1));
135       return 1;
136     }
137
138   dynscn = dwelf_strtab_add (shst, ".dynamic");
139
140   /* We'll need to know the section offset.  But this will be set up
141      by elf_update later, so for now just store the address.  */
142   const Elf32_Off *const dynscn_offset = &shdr->sh_offset;
143   shdr->sh_type = SHT_DYNAMIC;
144   shdr->sh_flags = SHF_ALLOC | SHF_WRITE;
145   shdr->sh_link = SHN_UNDEF;
146   shdr->sh_info = SHN_UNDEF;
147   /* This section will start here.  */
148   shdr->sh_addr = 0x1a0;
149
150   /* Create new section data.  */
151   Elf_Data *data = elf_newdata (scn);
152   if (data == NULL)
153     {
154       printf ("cannot create data for DYNAMIC section: %s\n", elf_errmsg (-1));
155       return 1;
156     }
157
158   /* Allocate memory for all the .dynamic entries.  */
159   Elf32_Dyn *dyn = malloc (ndtflags * sizeof (Elf32_Dyn));
160   if (dyn == NULL)
161     {
162       printf ("malloc failed: %m\n");
163       return 1;
164     }
165
166   /* Now write all the DT_* flags.  */
167   for (int i = 0; i < ndtflags; ++i)
168     {
169       dyn[i].d_tag = dtflags[i];
170       dyn[i].d_un.d_val = 0xdeadbeef;
171     }
172
173   /* Set the pointer to allocated memory.  */
174   data->d_buf = dyn;
175   data->d_type = ELF_T_DYN;
176   data->d_version = EV_CURRENT;
177   data->d_size = ndtflags * sizeof (Elf32_Dyn);
178   data->d_align = 0x8;
179
180   /* Create .shstrtab section.  */
181   scn = elf_newscn (elf);
182   if (scn == NULL)
183     {
184       printf ("cannot create SHSTRTAB section: %s\n", elf_errmsg (-1));
185       return 1;
186     }
187
188   shdr = elf32_getshdr (scn);
189   if (shdr == NULL)
190     {
191       printf ("cannot get header for SHSTRTAB section: %s\n", elf_errmsg (-1));
192       return 1;
193     }
194
195   shstrtabse = dwelf_strtab_add (shst, ".shstrtab");
196
197   shdr->sh_type = SHT_STRTAB;
198   shdr->sh_flags = 0;
199   shdr->sh_addr = 0;
200   shdr->sh_link = SHN_UNDEF;
201   shdr->sh_info = SHN_UNDEF;
202   shdr->sh_entsize = 1;
203
204   /* We have to store the section index in the ELF header.  */
205   ehdr->e_shstrndx = elf_ndxscn (scn);
206
207   data = elf_newdata (scn);
208   if (data == NULL)
209     {
210       printf ("cannot create data SHSTRTAB section: %s\n", elf_errmsg (-1));
211       return 1;
212     }
213
214   /* No more sections, finalize the section header string table.  */
215   dwelf_strtab_finalize (shst, data);
216
217   elf32_getshdr (elf_getscn (elf, 1))->sh_name = dwelf_strent_off (dynscn);
218   shdr->sh_name = dwelf_strent_off (shstrtabse);
219
220   /* Let the library compute the internal structure information.  */
221   if (elf_update (elf, ELF_C_NULL) < 0)
222     {
223       printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1));
224       return 1;
225     }
226
227   ehdr = elf32_getehdr (elf);
228
229   phdr[0].p_offset = ehdr->e_phoff;
230   phdr[0].p_vaddr = ehdr->e_phoff;
231   phdr[0].p_paddr = ehdr->e_phoff;
232   phdr[0].p_flags = PF_R | PF_X;
233   phdr[0].p_filesz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT);
234   phdr[0].p_memsz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT);
235   phdr[0].p_align = sizeof (Elf32_Word);
236
237   phdr[1].p_flags = PF_W | PF_R;
238   phdr[1].p_offset = *dynscn_offset;
239   /* Set up the start of this segment to equal start address of the
240      .dynamic section.  */
241   phdr[1].p_vaddr = 0x1a0;
242   phdr[1].p_paddr = 0x1a0;
243   phdr[1].p_align = 2 * sizeof (Elf32_Word);
244   phdr[1].p_filesz = ndtflags * sizeof (Elf32_Dyn);
245   phdr[1].p_memsz = ndtflags * sizeof (Elf32_Dyn);
246
247   /* Write out the file.  */
248   if (elf_update (elf, ELF_C_WRITE) < 0)
249     {
250       printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
251       return 1;
252     }
253
254   /* We don't need the string table anymore.  */
255   dwelf_strtab_free (shst);
256
257   /* And the data allocated in the .shstrtab section.  */
258   free (data->d_buf);
259
260   /* And the dynamic entries.  */
261   free (dyn);
262
263   /* All done.  */
264   if (elf_end (elf) != 0)
265     {
266       printf ("failure in elf_end: %s\n", elf_errmsg (-1));
267       return 1;
268     }
269
270   return 0;
271 }