1 /* Test program for elf_strptr function. 2 Copyright (C) 2015 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 #ifdef HAVE_CONFIG_H 19 # include <config.h> 20 #endif 21 22 #include <errno.h> 23 #include <fcntl.h> 24 #include <inttypes.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <unistd.h> 29 30 #include ELFUTILS_HEADER(elf) 31 #include <gelf.h> 32 33 34 /* Index of last string added. Returned by add_string (). */ 35 static size_t stridx = 0; 36 37 /* Some random strings. */ 38 static char *str1; 39 static size_t str1_off; 40 static char *str2; 41 static size_t str2_off; 42 static char *str3; 43 static size_t str3_off; 44 45 /* First three strings we write out. They should always be there. */ 46 static char *orig_str1; 47 static size_t orig_str1_off; 48 static char *orig_str2; 49 static size_t orig_str2_off; 50 static char *orig_str3; 51 static size_t orig_str3_off; 52 53 static void 54 check_orig_strings (Elf *elf, int ndx, const char *msg) 55 { 56 printf ("checking orig strings: %s\n", msg); 57 58 const char *str = elf_strptr (elf, ndx, 0); 59 printf ("\t'%s'\n", str); 60 if (str == NULL || strcmp ("", str) != 0) 61 exit (1); 62 63 str = elf_strptr (elf, ndx, 1); 64 printf ("\t'%s'\n", str); 65 if (str == NULL || strcmp (".strings", str) != 0) 66 exit (1); 67 68 str = elf_strptr (elf, ndx, orig_str1_off); 69 printf ("\t'%s'\n", str); 70 if (str == NULL || strcmp (orig_str1, str) != 0) 71 exit (1); 72 73 str = elf_strptr (elf, ndx, orig_str2_off); 74 printf ("\t'%s'\n", str); 75 if (str == NULL || strcmp (orig_str2, str) != 0) 76 exit (1); 77 78 str = elf_strptr (elf, ndx, orig_str3_off); 79 printf ("\t'%s'\n", str); 80 if (str == NULL || strcmp (orig_str3, str) != 0) 81 exit (1); 82 } 83 84 static void 85 check_strings (Elf *elf, int ndx, const char *msg) 86 { 87 check_orig_strings (elf, ndx, msg); 88 89 const char *str = elf_strptr (elf, ndx, str1_off); 90 printf ("\t'%s'\n", str); 91 if (str == NULL || strcmp (str1, str) != 0) 92 exit (1); 93 94 str = elf_strptr (elf, ndx, str2_off); 95 printf ("\t'%s'\n", str); 96 if (str == NULL || strcmp (str2, str) != 0) 97 exit (1); 98 99 str = elf_strptr (elf, ndx, str3_off); 100 printf ("\t'%s'\n", str); 101 if (str == NULL || strcmp (str3, str) != 0) 102 exit (1); 103 } 104 105 /* Adds a string and returns the offset in the section. */ 106 static size_t 107 add_string (Elf_Scn *scn, char *str) 108 { 109 size_t lastidx = stridx; 110 size_t size = strlen (str) + 1; 111 112 Elf_Data *data = elf_newdata (scn); 113 if (data == NULL) 114 { 115 printf ("cannot create data SHSTRTAB section: %s\n", elf_errmsg (-1)); 116 exit (1); 117 } 118 119 data->d_buf = str; 120 data->d_type = ELF_T_BYTE; 121 data->d_size = size; 122 data->d_align = 1; 123 data->d_version = EV_CURRENT; 124 125 stridx += size; 126 printf ("add_string: '%s', stridx: %zd, lastidx: %zd\n", 127 str, stridx, lastidx); 128 return lastidx; 129 } 130 131 static void 132 check_elf (const char *fname, int class, int use_mmap) 133 { 134 printf ("\nfname: %s\n", fname); 135 stridx = 0; 136 137 int fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, 0666); 138 if (fd == -1) 139 { 140 printf ("cannot open `%s': %s\n", fname, strerror (errno)); 141 exit (1); 142 } 143 144 Elf *elf = elf_begin (fd, use_mmap ? ELF_C_WRITE_MMAP : ELF_C_WRITE, NULL); 145 if (elf == NULL) 146 { 147 printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1)); 148 exit (1); 149 } 150 151 // Create an ELF header. 152 if (gelf_newehdr (elf, class) == 0) 153 { 154 printf ("cannot create ELF header: %s\n", elf_errmsg (-1)); 155 exit (1); 156 } 157 158 GElf_Ehdr ehdr_mem; 159 GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); 160 if (ehdr == NULL) 161 { 162 printf ("cannot get ELF header: %s\n", elf_errmsg (-1)); 163 exit (1); 164 } 165 166 // Initialize header. 167 ehdr->e_ident[EI_DATA] = class == ELFCLASS64 ? ELFDATA2LSB : ELFDATA2MSB; 168 ehdr->e_ident[EI_OSABI] = ELFOSABI_GNU; 169 ehdr->e_type = ET_NONE; 170 ehdr->e_machine = EM_X86_64; 171 ehdr->e_version = EV_CURRENT; 172 173 // Create strings section. 174 Elf_Scn *scn = elf_newscn (elf); 175 if (scn == NULL) 176 { 177 printf ("cannot create strings section: %s\n", elf_errmsg (-1)); 178 exit (1); 179 } 180 181 // Add an empty string to the table as NUL entry for section zero. 182 add_string (scn, ""); 183 184 GElf_Shdr shdr_mem; 185 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 186 if (shdr == NULL) 187 { 188 printf ("cannot get header for strings section: %s\n", elf_errmsg (-1)); 189 exit (1); 190 } 191 192 shdr->sh_type = SHT_STRTAB; 193 shdr->sh_flags = 0; 194 shdr->sh_addr = 0; 195 shdr->sh_link = SHN_UNDEF; 196 shdr->sh_info = SHN_UNDEF; 197 shdr->sh_addralign = 1; 198 shdr->sh_entsize = 0; 199 shdr->sh_name = add_string (scn, ".strings"); 200 201 // We have to store the section strtab index in the ELF header. 202 // So sections have actual names. 203 int ndx = elf_ndxscn (scn); 204 ehdr->e_shstrndx = ndx; 205 206 if (gelf_update_ehdr (elf, ehdr) == 0) 207 { 208 printf ("cannot update ELF header: %s\n", elf_errmsg (-1)); 209 exit (1); 210 } 211 212 // Add some random strings. These are the original ones. They should 213 // always be there (together with the empty "" and .strings section 214 // name strings. 215 orig_str1 = "elfutils"; 216 orig_str1_off = add_string (scn, orig_str1); 217 orig_str2 = "strtabelf"; 218 orig_str2_off = add_string (scn, orig_str2); 219 orig_str3 = "three"; 220 orig_str3_off = add_string (scn, orig_str3); 221 222 // Finished strings section, update the header. 223 if (gelf_update_shdr (scn, shdr) == 0) 224 { 225 printf ("cannot update STRTAB section header: %s\n", elf_errmsg (-1)); 226 exit (1); 227 } 228 229 // Let the library compute the internal structure information. 230 if (elf_update (elf, ELF_C_NULL) < 0) 231 { 232 printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1)); 233 exit (1); 234 } 235 236 // Check our strings are there. 237 check_orig_strings (elf, ndx, "first elf_update, before write"); 238 239 // Write everything to disk. 240 if (elf_update (elf, ELF_C_WRITE) < 0) 241 { 242 printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1)); 243 exit (1); 244 } 245 246 // Check out strings are there. 247 check_orig_strings (elf, ndx, "first elf_update, after write"); 248 249 // Add some more random strings. These will not be written to disk. 250 scn = elf_getscn (elf, ndx); 251 if (scn == NULL) 252 { 253 printf ("couldn't re-get strings section: %s\n", elf_errmsg (-1)); 254 exit (1); 255 } 256 257 str1 = "elfutils2"; 258 str1_off = add_string (scn, str1); 259 str2 = "strtabelf2"; 260 str2_off = add_string (scn, str2); 261 str3 = "three2"; 262 str3_off = add_string (scn, str3); 263 264 // Update internal structure information again. 265 if (elf_update (elf, ELF_C_NULL) < 0) 266 { 267 printf ("failure in re-elf_update(NULL): %s\n", elf_errmsg (-1)); 268 exit (1); 269 } 270 271 // Check our new strings are there. 272 check_strings (elf, ndx, "first extra strings"); 273 274 if (elf_end (elf) != 0) 275 { 276 printf ("failure in elf_end: %s\n", elf_errmsg (-1)); 277 exit (1); 278 } 279 280 close (fd); 281 282 /* Read the ELF from disk now. */ 283 fd = open (fname, O_RDWR, 0666); 284 if (fd == -1) 285 { 286 printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno)); 287 exit (1); 288 } 289 290 elf = elf_begin (fd, use_mmap ? ELF_C_RDWR_MMAP : ELF_C_RDWR, NULL); 291 if (elf == NULL) 292 { 293 printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1)); 294 exit (1); 295 } 296 297 /* Are our strings there? */ 298 check_orig_strings (elf, ndx, "read ELF file, orig strings"); 299 300 // Add some more random strings. 301 scn = elf_getscn (elf, ndx); 302 if (scn == NULL) 303 { 304 printf ("couldn't re-get strings section: %s\n", elf_errmsg (-1)); 305 exit (1); 306 } 307 308 shdr = gelf_getshdr (scn, &shdr_mem); 309 if (shdr == NULL) 310 { 311 printf ("cannot get header for strings section: %s\n", elf_errmsg (-1)); 312 exit (1); 313 } 314 315 // Reset stridx to end of section. 316 printf ("sh_size: %" PRIu64 "\n", shdr->sh_size); 317 stridx = shdr->sh_size; 318 319 str1 = "0123456789"; 320 str1_off = add_string (scn, str1); 321 str2 = "supercalifragilisticexpialidocious"; 322 str2_off = add_string (scn, str2); 323 str3 = "forty-two"; 324 str3_off = add_string (scn, str3); 325 326 // Update internal structure information. 327 if (elf_update (elf, ELF_C_NULL) < 0) 328 { 329 printf ("failure in rw-elf_update(NULL): %s\n", elf_errmsg (-1)); 330 exit (1); 331 } 332 333 /* Check our new strings are there. */ 334 check_strings (elf, ndx, "read file, added strings"); 335 336 // Write updated ELF file. 337 if (elf_update (elf, ELF_C_WRITE) < 0) 338 { 339 printf ("failure in re-elf_update(NULL): %s\n", elf_errmsg (-1)); 340 exit (1); 341 } 342 343 if (elf_end (elf) != 0) 344 { 345 printf ("failure in elf_end: %s\n", elf_errmsg (-1)); 346 exit (1); 347 } 348 349 close (fd); 350 351 // And read it in one last time. 352 fd = open (fname, O_RDONLY, 0666); 353 if (fd == -1) 354 { 355 printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno)); 356 exit (1); 357 } 358 359 elf = elf_begin (fd, use_mmap ? ELF_C_READ_MMAP : ELF_C_READ, NULL); 360 if (elf == NULL) 361 { 362 printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1)); 363 exit (1); 364 } 365 366 /* Are all our strings there? */ 367 check_strings (elf, ndx, "all together now"); 368 369 if (elf_end (elf) != 0) 370 { 371 printf ("failure in elf_end: %s\n", elf_errmsg (-1)); 372 exit (1); 373 } 374 375 close (fd); 376 377 unlink (fname); 378 } 379 380 int 381 main (int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused))) 382 { 383 elf_version (EV_CURRENT); 384 385 // Fill holes with something non-zero to more easily spot 386 // unterminated strings. 387 elf_fill ('X'); 388 389 check_elf ("strtab.elf.32", ELFCLASS32, 0); 390 check_elf ("strtab.elf.32.mmap", ELFCLASS32, 1); 391 check_elf ("strtab.elf.64", ELFCLASS64, 0); 392 check_elf ("strtab.elf.64.mmap", ELFCLASS64, 1); 393 394 return 0; 395 } 396 397