1/* Test program for adding a section to an empty 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 36/* Index of last string added. Returned by add_string (). */ 37static size_t stridx = 0; 38 39/* Adds a string and returns the offset in the section. */ 40static size_t 41add_string (Elf_Scn *scn, char *str) 42{ 43 size_t lastidx = stridx; 44 size_t size = strlen (str) + 1; 45 46 Elf_Data *data = elf_newdata (scn); 47 if (data == NULL) 48 { 49 printf ("cannot create data SHSTRTAB section: %s\n", elf_errmsg (-1)); 50 exit (1); 51 } 52 53 data->d_buf = str; 54 data->d_type = ELF_T_BYTE; 55 data->d_size = size; 56 data->d_align = 1; 57 data->d_version = EV_CURRENT; 58 59 stridx += size; 60 printf ("add_string: '%s', stridx: %zd, lastidx: %zd\n", 61 str, stridx, lastidx); 62 return lastidx; 63} 64 65static void 66check_elf (const char *fname, int class, int use_mmap) 67{ 68 printf ("\nfname: %s\n", fname); 69 stridx = 0; // Reset strtab strings index 70 71 int fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE); 72 if (fd == -1) 73 { 74 printf ("cannot open `%s': %s\n", fname, strerror (errno)); 75 exit (1); 76 } 77 78 Elf *elf = elf_begin (fd, use_mmap ? ELF_C_WRITE_MMAP : ELF_C_WRITE, NULL); 79 if (elf == NULL) 80 { 81 printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1)); 82 exit (1); 83 } 84 85 // Create an ELF header. 86 if (gelf_newehdr (elf, class) == 0) 87 { 88 printf ("cannot create ELF header: %s\n", elf_errmsg (-1)); 89 exit (1); 90 } 91 92 GElf_Ehdr ehdr_mem; 93 GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); 94 if (ehdr == NULL) 95 { 96 printf ("cannot get ELF header: %s\n", elf_errmsg (-1)); 97 exit (1); 98 } 99 100 // Initialize header. 101 ehdr->e_ident[EI_DATA] = class == ELFCLASS64 ? ELFDATA2LSB : ELFDATA2MSB; 102 ehdr->e_ident[EI_OSABI] = ELFOSABI_GNU; 103 ehdr->e_type = ET_NONE; 104 ehdr->e_machine = EM_X86_64; 105 ehdr->e_version = EV_CURRENT; 106 107 if (gelf_update_ehdr (elf, ehdr) == 0) 108 { 109 printf ("cannot update ELF header: %s\n", elf_errmsg (-1)); 110 exit (1); 111 } 112 113 // Write everything to disk. 114 if (elf_update (elf, ELF_C_WRITE) < 0) 115 { 116 printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1)); 117 exit (1); 118 } 119 120 if (elf_end (elf) != 0) 121 { 122 printf ("failure in elf_end: %s\n", elf_errmsg (-1)); 123 exit (1); 124 } 125 126 close (fd); 127 128 /* Reread the ELF from disk now. */ 129 fd = open (fname, O_RDWR); 130 if (fd == -1) 131 { 132 printf ("cannot (re)open `%s': %s\n", fname, strerror (errno)); 133 exit (1); 134 } 135 136 elf = elf_begin (fd, use_mmap ? ELF_C_RDWR_MMAP : ELF_C_RDWR, NULL); 137 if (elf == NULL) 138 { 139 printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1)); 140 exit (1); 141 } 142 143 // There are no sections yet. 144 if (elf_nextscn (elf, NULL) != NULL) 145 { 146 printf ("Empty elf had a section???\n"); 147 exit (1); 148 } 149 150 // Create strtab section. 151 Elf_Scn *scn = elf_newscn (elf); 152 if (scn == NULL) 153 { 154 printf ("cannot create strings section: %s\n", elf_errmsg (-1)); 155 exit (1); 156 } 157 158 // Add an empty string to the table as NUL entry for section zero. 159 add_string (scn, ""); 160 161 GElf_Shdr shdr_mem; 162 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 163 if (shdr == NULL) 164 { 165 printf ("cannot get header for strings section: %s\n", elf_errmsg (-1)); 166 exit (1); 167 } 168 169 shdr->sh_type = SHT_STRTAB; 170 shdr->sh_flags = 0; 171 shdr->sh_addr = 0; 172 shdr->sh_link = SHN_UNDEF; 173 shdr->sh_info = SHN_UNDEF; 174 shdr->sh_addralign = 1; 175 shdr->sh_entsize = 0; 176 shdr->sh_name = add_string (scn, ".strtab"); 177 178 // We have to store the section strtab index in the ELF header. 179 // So sections have actual names. 180 int ndx = elf_ndxscn (scn); 181 ehdr->e_shstrndx = ndx; 182 183 if (gelf_update_ehdr (elf, ehdr) == 0) 184 { 185 printf ("cannot update ELF header: %s\n", elf_errmsg (-1)); 186 exit (1); 187 } 188 189 // Finished strtab section, update the header. 190 if (gelf_update_shdr (scn, shdr) == 0) 191 { 192 printf ("cannot update STRTAB section header: %s\n", elf_errmsg (-1)); 193 exit (1); 194 } 195 196 // Write everything to disk. 197 if (elf_update (elf, ELF_C_WRITE) < 0) 198 { 199 printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1)); 200 exit (1); 201 } 202 203 if (elf_end (elf) != 0) 204 { 205 printf ("failure in elf_end: %s\n", elf_errmsg (-1)); 206 exit (1); 207 } 208 209 close (fd); 210 211 // And read it in one last time. 212 fd = open (fname, O_RDONLY); 213 if (fd == -1) 214 { 215 printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno)); 216 exit (1); 217 } 218 219 elf = elf_begin (fd, use_mmap ? ELF_C_READ_MMAP : ELF_C_READ, NULL); 220 if (elf == NULL) 221 { 222 printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1)); 223 exit (1); 224 } 225 226 // Is our new section there? 227 scn = elf_nextscn (elf, NULL); 228 if (scn == NULL) 229 { 230 printf ("cannot get new section: %s\n", elf_errmsg (-1)); 231 exit (1); 232 } 233 234 shdr = gelf_getshdr (scn, &shdr_mem); 235 if (shdr == NULL) 236 { 237 printf ("cannot get header for new section: %s\n", elf_errmsg (-1)); 238 exit (1); 239 } 240 241 size_t shstrndx; 242 if (elf_getshdrstrndx (elf, &shstrndx) < 0) 243 { 244 printf ("elf_getshdrstrndx: %s\n", elf_errmsg (-1)); 245 exit (1); 246 } 247 248 const char *sname = elf_strptr (elf, shstrndx, shdr->sh_name); 249 if (sname == NULL || strcmp (sname, ".strtab") != 0) 250 { 251 printf ("Bad section name: %s\n", sname); 252 exit (1); 253 } 254 255 if (elf_end (elf) != 0) 256 { 257 printf ("failure in elf_end: %s\n", elf_errmsg (-1)); 258 exit (1); 259 } 260 261 close (fd); 262 263 unlink (fname); 264} 265 266int 267main (int argc __attribute__ ((unused)), 268 char *argv[] __attribute__ ((unused))) 269{ 270 elf_version (EV_CURRENT); 271 272 check_elf ("empty.elf.32", ELFCLASS32, 0); 273 check_elf ("empty.elf.32.mmap", ELFCLASS32, 1); 274 check_elf ("empty.elf.64", ELFCLASS64, 0); 275 check_elf ("empty.elf.64.mmap", ELFCLASS64, 1); 276 277 return 0; 278} 279