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