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 31 #include ELFUTILS_HEADER(elf) 32 #include <gelf.h> 33 34 void 35 check_elf (const char *fname, int class, int use_mmap) 36 { 37 printf ("\nfname: %s\n", fname); 38 39 int fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, 0666); 40 if (fd == -1) 41 { 42 printf ("cannot open `%s': %s\n", fname, strerror (errno)); 43 exit (1); 44 } 45 46 Elf *elf = elf_begin (fd, use_mmap ? ELF_C_WRITE_MMAP : ELF_C_WRITE, NULL); 47 if (elf == NULL) 48 { 49 printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1)); 50 exit (1); 51 } 52 53 // Create an ELF header. 54 if (gelf_newehdr (elf, class) == 0) 55 { 56 printf ("cannot create ELF header: %s\n", elf_errmsg (-1)); 57 exit (1); 58 } 59 60 GElf_Ehdr ehdr_mem; 61 GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); 62 if (ehdr == NULL) 63 { 64 printf ("cannot get ELF header: %s\n", elf_errmsg (-1)); 65 exit (1); 66 } 67 68 // Initialize header. 69 ehdr->e_ident[EI_DATA] = class == ELFCLASS64 ? ELFDATA2LSB : ELFDATA2MSB; 70 ehdr->e_ident[EI_OSABI] = ELFOSABI_GNU; 71 ehdr->e_type = ET_LOOS + 1; 72 ehdr->e_machine = EM_X86_64; 73 ehdr->e_version = EV_CURRENT; 74 75 if (gelf_update_ehdr (elf, ehdr) == 0) 76 { 77 printf ("cannot update ELF header: %s\n", elf_errmsg (-1)); 78 exit (1); 79 } 80 81 // Create a program header. 82 if (gelf_newphdr (elf, 1) == 0) 83 { 84 printf ("cannot create program header: %s\n", elf_errmsg (-1)); 85 exit (1); 86 } 87 88 GElf_Phdr phdr; 89 if (gelf_getphdr (elf, 0, &phdr) == NULL) 90 { 91 printf ("cannot get program header: %s\n", elf_errmsg (-1)); 92 exit (1); 93 } 94 95 // Some random values to check later. 96 phdr.p_type = PT_NULL; 97 phdr.p_offset = 0; 98 phdr.p_vaddr = 0; 99 phdr.p_paddr = 1; 100 phdr.p_filesz = 0; 101 phdr.p_memsz = 1024; 102 phdr.p_flags = PF_R; 103 phdr.p_align = 16; 104 105 if (gelf_update_phdr (elf, 0, &phdr) == 0) 106 { 107 printf ("cannot update program header: %s\n", elf_errmsg (-1)); 108 exit (1); 109 } 110 111 // Write everything to disk. 112 if (elf_update (elf, ELF_C_WRITE) < 0) 113 { 114 printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1)); 115 exit (1); 116 } 117 118 if (elf_end (elf) != 0) 119 { 120 printf ("failure in elf_end: %s\n", elf_errmsg (-1)); 121 exit (1); 122 } 123 124 close (fd); 125 126 /* Reread the ELF from disk now. */ 127 fd = open (fname, O_RDONLY, 0666); 128 if (fd == -1) 129 { 130 printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno)); 131 exit (1); 132 } 133 134 elf = elf_begin (fd, use_mmap ? ELF_C_READ_MMAP : ELF_C_READ, NULL); 135 if (elf == NULL) 136 { 137 printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1)); 138 exit (1); 139 } 140 141 // Is our phdr there? 142 size_t phnum; 143 if (elf_getphdrnum (elf, &phnum) != 0) 144 { 145 printf ("cannot get phdr num: %s\n", elf_errmsg (-1)); 146 exit (1); 147 } 148 149 if (phnum != 1) 150 { 151 printf ("Expected just 1 phdr, got: %zd\n", phnum); 152 exit (1); 153 } 154 155 if (gelf_getphdr (elf, 0, &phdr) == NULL) 156 { 157 printf ("cannot get program header from file: %s\n", elf_errmsg (-1)); 158 exit (1); 159 } 160 161 if (phdr.p_type != PT_NULL 162 || phdr.p_offset != 0 163 || phdr.p_vaddr != 0 164 || phdr.p_paddr != 1 165 || phdr.p_filesz != 0 166 || phdr.p_memsz != 1024 167 || phdr.p_flags != PF_R 168 || phdr.p_align != 16) 169 { 170 printf ("Unexpected phdr values\n"); 171 exit (1); 172 } 173 174 if (elf_end (elf) != 0) 175 { 176 printf ("failure in elf_end: %s\n", elf_errmsg (-1)); 177 exit (1); 178 } 179 180 close (fd); 181 182 unlink (fname); 183 } 184 185 int 186 main (int argc __attribute__ ((unused)), 187 char *argv[] __attribute__ ((unused))) 188 { 189 elf_version (EV_CURRENT); 190 191 check_elf ("vendor.elf.32", ELFCLASS32, 0); 192 check_elf ("vendor.elf.32.mmap", ELFCLASS32, 1); 193 check_elf ("vendor.elf.64", ELFCLASS64, 0); 194 check_elf ("vendor.elf.64.mmap", ELFCLASS64, 1); 195 196 return 0; 197 } 198