• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
main(void)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_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       DT_NULL
66     };
67   const int ndtflags = sizeof (dtflags) / sizeof (dtflags[0]);
68 
69   /* We use no threads here which can interfere with handling a stream.  */
70   (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
71 
72   /* Open the file.  */
73   int fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
74   if (fd == -1)
75     {
76       printf ("cannot open `%s': %m\n", fname);
77       return 1;
78     }
79 
80   /* Tell the library which version are we expecting.  */
81   elf_version (EV_CURRENT);
82 
83   /* Create an ELF descriptor.  */
84   Elf *elf = elf_begin (fd, ELF_C_WRITE, NULL);
85   if (elf == NULL)
86     {
87       printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
88       return 1;
89     }
90 
91   /* Create an ELF header.  */
92   Elf32_Ehdr *ehdr = elf32_newehdr (elf);
93   if (ehdr == NULL)
94     {
95       printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
96       return 1;
97     }
98 
99   ehdr->e_ident[0] = 42;
100   ehdr->e_ident[5] = 1;
101   ehdr->e_ident[6] = 2;
102   ehdr->e_type = ET_EXEC;
103   ehdr->e_machine = EM_386;
104   ehdr->e_version = 1;
105   ehdr->e_ehsize = 1;
106   ehdr->e_shnum = 3;
107 
108   elf_flagehdr (elf, ELF_C_SET, ELF_F_DIRTY);
109 
110   /* Create the program headers.  */
111   Elf32_Phdr *phdr = elf32_newphdr (elf, 2);
112   if (phdr == NULL)
113     {
114       printf ("cannot create program headers: %s\n", elf_errmsg (-1));
115       return 1;
116     }
117 
118   phdr[0].p_type = PT_PHDR;
119   phdr[1].p_type = PT_DYNAMIC;
120 
121   elf_flagphdr (elf, ELF_C_SET, ELF_F_DIRTY);
122   shst = dwelf_strtab_init (true);
123 
124   /* Create the .dynamic section.  */
125   Elf_Scn *scn = elf_newscn (elf);
126   if (scn == NULL)
127     {
128       printf ("cannot create DYNAMIC section: %s\n", elf_errmsg (-1));
129       return 1;
130     }
131 
132   Elf32_Shdr *shdr = elf32_getshdr (scn);
133   if (shdr == NULL)
134     {
135       printf ("cannot get header for DYNAMIC section: %s\n", elf_errmsg (-1));
136       return 1;
137     }
138 
139   dynscn = dwelf_strtab_add (shst, ".dynamic");
140 
141   /* We'll need to know the section offset.  But this will be set up
142      by elf_update later, so for now just store the address.  */
143   const Elf32_Off *const dynscn_offset = &shdr->sh_offset;
144   shdr->sh_type = SHT_DYNAMIC;
145   shdr->sh_flags = SHF_ALLOC | SHF_WRITE;
146   shdr->sh_link = SHN_UNDEF;
147   shdr->sh_info = SHN_UNDEF;
148   /* This section will start here.  */
149   shdr->sh_addr = 0x1a0;
150 
151   /* Create new section data.  */
152   Elf_Data *data = elf_newdata (scn);
153   if (data == NULL)
154     {
155       printf ("cannot create data for DYNAMIC section: %s\n", elf_errmsg (-1));
156       return 1;
157     }
158 
159   /* Allocate memory for all the .dynamic entries.  */
160   Elf32_Dyn *dyn = malloc (ndtflags * sizeof (Elf32_Dyn));
161   if (dyn == NULL)
162     {
163       printf ("malloc failed: %m\n");
164       return 1;
165     }
166 
167   /* Now write all the DT_* flags.  */
168   for (int i = 0; i < ndtflags; ++i)
169     {
170       dyn[i].d_tag = dtflags[i];
171       dyn[i].d_un.d_val = 0xdeadbeef;
172     }
173 
174   /* Set the pointer to allocated memory.  */
175   data->d_buf = dyn;
176   data->d_type = ELF_T_DYN;
177   data->d_version = EV_CURRENT;
178   data->d_size = ndtflags * sizeof (Elf32_Dyn);
179   data->d_align = 0x8;
180 
181   /* Create .shstrtab section.  */
182   scn = elf_newscn (elf);
183   if (scn == NULL)
184     {
185       printf ("cannot create SHSTRTAB section: %s\n", elf_errmsg (-1));
186       return 1;
187     }
188 
189   shdr = elf32_getshdr (scn);
190   if (shdr == NULL)
191     {
192       printf ("cannot get header for SHSTRTAB section: %s\n", elf_errmsg (-1));
193       return 1;
194     }
195 
196   shstrtabse = dwelf_strtab_add (shst, ".shstrtab");
197 
198   shdr->sh_type = SHT_STRTAB;
199   shdr->sh_flags = 0;
200   shdr->sh_addr = 0;
201   shdr->sh_link = SHN_UNDEF;
202   shdr->sh_info = SHN_UNDEF;
203   shdr->sh_entsize = 1;
204 
205   /* We have to store the section index in the ELF header.  */
206   ehdr->e_shstrndx = elf_ndxscn (scn);
207 
208   data = elf_newdata (scn);
209   if (data == NULL)
210     {
211       printf ("cannot create data SHSTRTAB section: %s\n", elf_errmsg (-1));
212       return 1;
213     }
214 
215   /* No more sections, finalize the section header string table.  */
216   dwelf_strtab_finalize (shst, data);
217 
218   elf32_getshdr (elf_getscn (elf, 1))->sh_name = dwelf_strent_off (dynscn);
219   shdr->sh_name = dwelf_strent_off (shstrtabse);
220 
221   /* Let the library compute the internal structure information.  */
222   if (elf_update (elf, ELF_C_NULL) < 0)
223     {
224       printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1));
225       return 1;
226     }
227 
228   ehdr = elf32_getehdr (elf);
229 
230   phdr[0].p_offset = ehdr->e_phoff;
231   phdr[0].p_vaddr = ehdr->e_phoff;
232   phdr[0].p_paddr = ehdr->e_phoff;
233   phdr[0].p_flags = PF_R | PF_X;
234   phdr[0].p_filesz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT);
235   phdr[0].p_memsz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT);
236   phdr[0].p_align = sizeof (Elf32_Word);
237 
238   phdr[1].p_flags = PF_W | PF_R;
239   phdr[1].p_offset = *dynscn_offset;
240   /* Set up the start of this segment to equal start address of the
241      .dynamic section.  */
242   phdr[1].p_vaddr = 0x1a0;
243   phdr[1].p_paddr = 0x1a0;
244   phdr[1].p_align = 2 * sizeof (Elf32_Word);
245   phdr[1].p_filesz = ndtflags * sizeof (Elf32_Dyn);
246   phdr[1].p_memsz = ndtflags * sizeof (Elf32_Dyn);
247 
248   /* Write out the file.  */
249   if (elf_update (elf, ELF_C_WRITE) < 0)
250     {
251       printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
252       return 1;
253     }
254 
255   /* We don't need the string table anymore.  */
256   dwelf_strtab_free (shst);
257 
258   /* And the data allocated in the .shstrtab section.  */
259   free (data->d_buf);
260 
261   /* And the dynamic entries.  */
262   free (dyn);
263 
264   /* All done.  */
265   if (elf_end (elf) != 0)
266     {
267       printf ("failure in elf_end: %s\n", elf_errmsg (-1));
268       return 1;
269     }
270 
271   return 0;
272 }
273