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