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.
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.
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.
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.
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>. */
31 #include ELFUTILS_HEADER(ebl)
37 #include <stdio_ext.h>
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[] =
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
73 const int ndtflags = sizeof (dtflags) / sizeof (dtflags[0]);
75 /* We use no threads here which can interfere with handling a stream. */
76 (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
79 int fd = open64 (fname, O_RDWR | O_CREAT | O_TRUNC, 0666);
82 printf ("cannot open `%s': %m\n", fname);
86 /* Tell the library which version are we expecting. */
87 elf_version (EV_CURRENT);
89 /* Create an ELF descriptor. */
90 Elf *elf = elf_begin (fd, ELF_C_WRITE, NULL);
93 printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
97 /* Create an ELF header. */
98 Elf32_Ehdr *ehdr = elf32_newehdr (elf);
101 printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
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;
114 elf_flagehdr (elf, ELF_C_SET, ELF_F_DIRTY);
116 /* Create the program headers. */
117 Elf32_Phdr *phdr = elf32_newphdr (elf, 2);
120 printf ("cannot create program headers: %s\n", elf_errmsg (-1));
124 phdr[0].p_type = PT_PHDR;
125 phdr[1].p_type = PT_DYNAMIC;
127 elf_flagphdr (elf, ELF_C_SET, ELF_F_DIRTY);
128 shst = ebl_strtabinit (true);
130 /* Create the .dynamic section. */
131 Elf_Scn *scn = elf_newscn (elf);
134 printf ("cannot create DYNAMIC section: %s\n", elf_errmsg (-1));
138 Elf32_Shdr *shdr = elf32_getshdr (scn);
141 printf ("cannot get header for DYNAMIC section: %s\n", elf_errmsg (-1));
145 dynscn = ebl_strtabadd (shst, ".dynamic", 0);
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;
157 /* Create new section data. */
158 Elf_Data *data = elf_newdata (scn);
161 printf ("cannot create data for DYNAMIC section: %s\n", elf_errmsg (-1));
165 /* Allocate memory for all the .dynamic entries. */
166 Elf32_Dyn *dyn = malloc (ndtflags * sizeof (Elf32_Dyn));
169 printf ("malloc failed: %m\n");
173 /* Now write all the DT_* flags. */
174 for (int i = 0; i < ndtflags; ++i)
176 dyn[i].d_tag = dtflags[i];
177 dyn[i].d_un.d_val = 0xdeadbeef;
180 /* Set the pointer to allocated memory. */
182 data->d_type = ELF_T_DYN;
183 data->d_version = EV_CURRENT;
184 data->d_size = ndtflags * sizeof (Elf32_Dyn);
187 /* Create .shstrtab section. */
188 scn = elf_newscn (elf);
191 printf ("cannot create SHSTRTAB section: %s\n", elf_errmsg (-1));
195 shdr = elf32_getshdr (scn);
198 printf ("cannot get header for SHSTRTAB section: %s\n", elf_errmsg (-1));
202 shstrtabse = ebl_strtabadd (shst, ".shstrtab", 0);
204 shdr->sh_type = SHT_STRTAB;
207 shdr->sh_link = SHN_UNDEF;
208 shdr->sh_info = SHN_UNDEF;
209 shdr->sh_entsize = 1;
211 /* We have to store the section index in the ELF header. */
212 ehdr->e_shstrndx = elf_ndxscn (scn);
214 data = elf_newdata (scn);
217 printf ("cannot create data SHSTRTAB section: %s\n", elf_errmsg (-1));
221 /* No more sections, finalize the section header string table. */
222 ebl_strtabfinalize (shst, data);
224 elf32_getshdr (elf_getscn (elf, 1))->sh_name = ebl_strtaboffset (dynscn);
225 shdr->sh_name = ebl_strtaboffset (shstrtabse);
227 /* Let the library compute the internal structure information. */
228 if (elf_update (elf, ELF_C_NULL) < 0)
230 printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1));
234 ehdr = elf32_getehdr (elf);
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);
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
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);
254 /* Write out the file. */
255 if (elf_update (elf, ELF_C_WRITE) < 0)
257 printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
261 /* We don't need the string table anymore. */
262 ebl_strtabfree (shst);
264 /* And the data allocated in the .shstrtab section. */
268 if (elf_end (elf) != 0)
270 printf ("failure in elf_end: %s\n", elf_errmsg (-1));