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