• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Test program for adding a program header to a vendor specific ELF file.
2    Copyright (C) 2016 Red Hat, Inc.
3    This file is part of elfutils.
4 
5    This file is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9 
10    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
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17 
18 
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22 
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <inttypes.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include "system.h"
31 
32 #include ELFUTILS_HEADER(elf)
33 #include <gelf.h>
34 
35 void
check_elf(const char * fname,int class,int use_mmap)36 check_elf (const char *fname, int class, int use_mmap)
37 {
38   printf ("\nfname: %s\n", fname);
39 
40   int fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
41   if (fd == -1)
42     {
43       printf ("cannot open `%s': %s\n", fname, strerror (errno));
44       exit (1);
45     }
46 
47   Elf *elf = elf_begin (fd, use_mmap ? ELF_C_WRITE_MMAP : ELF_C_WRITE, NULL);
48   if (elf == NULL)
49     {
50       printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
51       exit (1);
52     }
53 
54   // Create an ELF header.
55   if (gelf_newehdr (elf, class) == 0)
56     {
57       printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
58       exit (1);
59     }
60 
61   GElf_Ehdr ehdr_mem;
62   GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
63   if (ehdr == NULL)
64     {
65       printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
66       exit (1);
67     }
68 
69   // Initialize header.
70   ehdr->e_ident[EI_DATA] = class == ELFCLASS64 ? ELFDATA2LSB : ELFDATA2MSB;
71   ehdr->e_ident[EI_OSABI] = ELFOSABI_GNU;
72   ehdr->e_type = ET_LOOS + 1;
73   ehdr->e_machine = EM_X86_64;
74   ehdr->e_version = EV_CURRENT;
75 
76   if (gelf_update_ehdr (elf, ehdr) == 0)
77     {
78       printf ("cannot update ELF header: %s\n", elf_errmsg (-1));
79       exit (1);
80     }
81 
82   // Create a program header.
83   if (gelf_newphdr (elf, 1) == 0)
84     {
85       printf ("cannot create program header: %s\n", elf_errmsg (-1));
86       exit (1);
87     }
88 
89   GElf_Phdr phdr;
90   if (gelf_getphdr (elf, 0, &phdr) == NULL)
91     {
92       printf ("cannot get program header: %s\n", elf_errmsg (-1));
93       exit (1);
94     }
95 
96   // Some random values to check later.
97   phdr.p_type = PT_NULL;
98   phdr.p_offset = 0;
99   phdr.p_vaddr = 0;
100   phdr.p_paddr = 1;
101   phdr.p_filesz = 0;
102   phdr.p_memsz = 1024;
103   phdr.p_flags = PF_R;
104   phdr.p_align = 16;
105 
106   if (gelf_update_phdr (elf, 0, &phdr) == 0)
107     {
108       printf ("cannot update program header: %s\n", elf_errmsg (-1));
109       exit (1);
110     }
111 
112   // Write everything to disk.
113   if (elf_update (elf, ELF_C_WRITE) < 0)
114     {
115       printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
116       exit (1);
117     }
118 
119   if (elf_end (elf) != 0)
120     {
121       printf ("failure in elf_end: %s\n", elf_errmsg (-1));
122       exit (1);
123     }
124 
125   close (fd);
126 
127   /* Reread the ELF from disk now.  */
128   fd = open (fname, O_RDONLY);
129   if (fd == -1)
130     {
131       printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
132       exit (1);
133     }
134 
135   elf = elf_begin (fd, use_mmap ? ELF_C_READ_MMAP : ELF_C_READ, NULL);
136   if (elf == NULL)
137     {
138       printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1));
139       exit (1);
140     }
141 
142   // Is our phdr there?
143   size_t phnum;
144   if (elf_getphdrnum (elf, &phnum) != 0)
145     {
146       printf ("cannot get phdr num: %s\n", elf_errmsg (-1));
147       exit (1);
148     }
149 
150   if (phnum != 1)
151     {
152       printf ("Expected just 1 phdr, got: %zd\n", phnum);
153       exit (1);
154     }
155 
156   if (gelf_getphdr (elf, 0, &phdr) == NULL)
157     {
158       printf ("cannot get program header from file: %s\n", elf_errmsg (-1));
159       exit (1);
160     }
161 
162   if (phdr.p_type != PT_NULL
163       || phdr.p_offset != 0
164       || phdr.p_vaddr != 0
165       || phdr.p_paddr != 1
166       || phdr.p_filesz != 0
167       || phdr.p_memsz != 1024
168       || phdr.p_flags != PF_R
169       || phdr.p_align != 16)
170     {
171       printf ("Unexpected phdr values\n");
172       exit (1);
173     }
174 
175   if (elf_end (elf) != 0)
176     {
177       printf ("failure in elf_end: %s\n", elf_errmsg (-1));
178       exit (1);
179     }
180 
181   close (fd);
182 
183   unlink (fname);
184 }
185 
186 int
main(int argc,char * argv[])187 main (int argc __attribute__ ((unused)),
188       char *argv[] __attribute__ ((unused)))
189 {
190   elf_version (EV_CURRENT);
191 
192   check_elf ("vendor.elf.32", ELFCLASS32, 0);
193   check_elf ("vendor.elf.32.mmap", ELFCLASS32, 1);
194   check_elf ("vendor.elf.64", ELFCLASS64, 0);
195   check_elf ("vendor.elf.64.mmap", ELFCLASS64, 1);
196 
197   return 0;
198 }
199