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