xref: /third_party/elfutils/tests/vendorelf.c (revision da0c48c4)
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
35void
36check_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
186int
187main (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