1 /* Compress or decompress an ELF file. 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 #include <config.h> 19 #include <assert.h> 20 #include <argp.h> 21 #include <error.h> 22 #include <stdbool.h> 23 #include <stdlib.h> 24 #include <inttypes.h> 25 #include <stdio.h> 26 #include <string.h> 27 #include <locale.h> 28 #include <fcntl.h> 29 #include <fnmatch.h> 30 #include <sys/types.h> 31 #include <sys/stat.h> 32 #include <unistd.h> 33 #include ELFUTILS_HEADER(elf) 34 #include ELFUTILS_HEADER(ebl) 35 #include <gelf.h> 36 #include "system.h" 37 38 /* Name and version of program. */ 39 static void print_version (FILE *stream, struct argp_state *state); 40 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version; 41 42 /* Bug report address. */ 43 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT; 44 45 static int verbose = 0; /* < 0, no warnings, > 0 extra verbosity. */ 46 static bool force = false; 47 static bool permissive = false; 48 static const char *foutput = NULL; 49 50 #define T_UNSET 0 51 #define T_DECOMPRESS 1 /* none */ 52 #define T_COMPRESS_ZLIB 2 /* zlib */ 53 #define T_COMPRESS_GNU 3 /* zlib-gnu */ 54 static int type = T_UNSET; 55 56 static void 57 print_version (FILE *stream, struct argp_state *state __attribute__ ((unused))) 58 { 59 fprintf (stream, "elfcompress (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); 60 } 61 62 struct section_pattern 63 { 64 char *pattern; 65 struct section_pattern *next; 66 }; 67 68 static struct section_pattern *patterns = NULL; 69 70 static void 71 add_pattern (const char *pattern) 72 { 73 struct section_pattern *p = xmalloc (sizeof *p); 74 p->pattern = xstrdup (pattern); 75 p->next = patterns; 76 patterns = p; 77 } 78 79 static void 80 free_patterns (void) 81 { 82 struct section_pattern *pattern = patterns; 83 while (pattern != NULL) 84 { 85 struct section_pattern *p = pattern; 86 pattern = p->next; 87 free (p->pattern); 88 free (p); 89 } 90 } 91 92 static error_t 93 parse_opt (int key, char *arg __attribute__ ((unused)), 94 struct argp_state *state __attribute__ ((unused))) 95 { 96 switch (key) 97 { 98 case 'v': 99 verbose++; 100 break; 101 102 case 'q': 103 verbose--; 104 105 case 'f': 106 force = true; 107 break; 108 109 case 'p': 110 permissive = true; 111 break; 112 113 case 'n': 114 add_pattern (arg); 115 break; 116 117 case 'o': 118 if (foutput != NULL) 119 argp_error (state, N_("-o option specified twice")); 120 else 121 foutput = arg; 122 break; 123 124 case 't': 125 if (type != T_UNSET) 126 argp_error (state, N_("-t option specified twice")); 127 128 if (strcmp ("none", arg) == 0) 129 type = T_DECOMPRESS; 130 else if (strcmp ("zlib", arg) == 0 || strcmp ("zlib-gabi", arg) == 0) 131 type = T_COMPRESS_ZLIB; 132 else if (strcmp ("zlib-gnu", arg) == 0 || strcmp ("gnu", arg) == 0) 133 type = T_COMPRESS_GNU; 134 else 135 argp_error (state, N_("unknown compression type '%s'"), arg); 136 break; 137 138 case ARGP_KEY_SUCCESS: 139 if (type == T_UNSET) 140 type = T_COMPRESS_ZLIB; 141 if (patterns == NULL) 142 add_pattern (".?(z)debug*"); 143 break; 144 145 case ARGP_KEY_NO_ARGS: 146 /* We need at least one input file. */ 147 argp_error (state, N_("No input file given")); 148 break; 149 150 case ARGP_KEY_ARGS: 151 if (foutput != NULL && state->argc - state->next > 1) 152 argp_error (state, 153 N_("Only one input file allowed together with '-o'")); 154 /* We only use this for checking the number of arguments, we don't 155 actually want to consume them, so fallthrough. */ 156 default: 157 return ARGP_ERR_UNKNOWN; 158 } 159 return 0; 160 } 161 162 static bool 163 section_name_matches (const char *name) 164 { 165 struct section_pattern *pattern = patterns; 166 while (pattern != NULL) 167 { 168 if (fnmatch (pattern->pattern, name, FNM_EXTMATCH) == 0) 169 return true; 170 pattern = pattern->next; 171 } 172 return false; 173 } 174 175 static int 176 setshdrstrndx (Elf *elf, GElf_Ehdr *ehdr, size_t ndx) 177 { 178 if (ndx < SHN_LORESERVE) 179 ehdr->e_shstrndx = ndx; 180 else 181 { 182 ehdr->e_shstrndx = SHN_XINDEX; 183 Elf_Scn *zscn = elf_getscn (elf, 0); 184 GElf_Shdr zshdr_mem; 185 GElf_Shdr *zshdr = gelf_getshdr (zscn, &zshdr_mem); 186 if (zshdr == NULL) 187 return -1; 188 zshdr->sh_link = ndx; 189 if (gelf_update_shdr (zscn, zshdr) == 0) 190 return -1; 191 } 192 193 if (gelf_update_ehdr (elf, ehdr) == 0) 194 return -1; 195 196 return 0; 197 } 198 199 static int 200 compress_section (Elf_Scn *scn, size_t orig_size, const char *name, 201 const char *newname, size_t ndx, 202 bool gnu, bool compress, bool report_verbose) 203 { 204 int res; 205 unsigned int flags = compress && force ? ELF_CHF_FORCE : 0; 206 if (gnu) 207 res = elf_compress_gnu (scn, compress ? 1 : 0, flags); 208 else 209 res = elf_compress (scn, compress ? ELFCOMPRESS_ZLIB : 0, flags); 210 211 if (res < 0) 212 error (0, 0, "Couldn't decompress section [%zd] %s: %s", 213 ndx, name, elf_errmsg (-1)); 214 else 215 { 216 if (compress && res == 0) 217 { 218 if (verbose >= 0) 219 printf ("[%zd] %s NOT compressed, wouldn't be smaller\n", 220 ndx, name); 221 } 222 223 if (report_verbose && res > 0) 224 { 225 printf ("[%zd] %s %s", ndx, name, 226 compress ? "compressed" : "decompressed"); 227 if (newname != NULL) 228 printf (" -> %s", newname); 229 230 /* Reload shdr, it has changed. */ 231 GElf_Shdr shdr_mem; 232 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 233 if (shdr == NULL) 234 { 235 error (0, 0, "Couldn't get shdr for section [%zd]", ndx); 236 return -1; 237 } 238 float new = shdr->sh_size; 239 float orig = orig_size ?: 1; 240 printf (" (%zu => %" PRIu64 " %.2f%%)\n", 241 orig_size, shdr->sh_size, (new / orig) * 100); 242 } 243 } 244 245 return res; 246 } 247 248 static int 249 process_file (const char *fname) 250 { 251 if (verbose > 0) 252 printf ("processing: %s\n", fname); 253 254 /* The input ELF. */ 255 int fd = -1; 256 Elf *elf = NULL; 257 258 /* The output ELF. */ 259 char *fnew = NULL; 260 int fdnew = -1; 261 Elf *elfnew = NULL; 262 263 /* Buffer for (one) new section name if necessary. */ 264 char *snamebuf = NULL; 265 266 /* String table (and symbol table), if section names need adjusting. */ 267 struct Ebl_Strtab *names = NULL; 268 struct Ebl_Strent **scnstrents = NULL; 269 struct Ebl_Strent **symstrents = NULL; 270 char **scnnames = NULL; 271 272 /* Section data from names. */ 273 void *namesbuf = NULL; 274 275 /* Which sections match and need to be (un)compressed. */ 276 unsigned int *sections = NULL; 277 278 /* How many sections are we talking about? */ 279 size_t shnum = 0; 280 281 #define WORD_BITS (8U * sizeof (unsigned int)) 282 void set_section (size_t ndx) 283 { 284 sections[ndx / WORD_BITS] |= (1U << (ndx % WORD_BITS)); 285 } 286 287 bool get_section (size_t ndx) 288 { 289 return (sections[ndx / WORD_BITS] & (1U << (ndx % WORD_BITS))) != 0; 290 } 291 292 int cleanup (int res) 293 { 294 elf_end (elf); 295 close (fd); 296 297 elf_end (elfnew); 298 close (fdnew); 299 300 if (fnew != NULL) 301 { 302 unlink (fnew); 303 free (fnew); 304 fnew = NULL; 305 } 306 307 free (snamebuf); 308 if (names != NULL) 309 { 310 ebl_strtabfree (names); 311 free (scnstrents); 312 free (symstrents); 313 free (namesbuf); 314 if (scnnames != NULL) 315 { 316 for (size_t n = 0; n < shnum; n++) 317 free (scnnames[n]); 318 free (scnnames); 319 } 320 } 321 322 free (sections); 323 324 return res; 325 } 326 327 fd = open (fname, O_RDONLY); 328 if (fd < 0) 329 { 330 error (0, errno, "Couldn't open %s\n", fname); 331 return cleanup (-1); 332 } 333 334 elf = elf_begin (fd, ELF_C_READ, NULL); 335 if (elf == NULL) 336 { 337 error (0, 0, "Couldn't open ELF file %s for reading: %s", 338 fname, elf_errmsg (-1)); 339 return cleanup (-1); 340 } 341 342 /* We dont' handle ar files (or anything else), we probably should. */ 343 Elf_Kind kind = elf_kind (elf); 344 if (kind != ELF_K_ELF) 345 { 346 if (kind == ELF_K_AR) 347 error (0, 0, "Cannot handle ar files: %s", fname); 348 else 349 error (0, 0, "Unknown file type: %s", fname); 350 return cleanup (-1); 351 } 352 353 struct stat st; 354 if (fstat (fd, &st) != 0) 355 { 356 error (0, errno, "Couldn't fstat %s", fname); 357 return cleanup (-1); 358 } 359 360 GElf_Ehdr ehdr; 361 if (gelf_getehdr (elf, &ehdr) == NULL) 362 { 363 error (0, 0, "Couldn't get ehdr for %s: %s", fname, elf_errmsg (-1)); 364 return cleanup (-1); 365 } 366 367 /* Get the section header string table. */ 368 size_t shdrstrndx; 369 if (elf_getshdrstrndx (elf, &shdrstrndx) != 0) 370 { 371 error (0, 0, "Couldn't get section header string table index in %s: %s", 372 fname, elf_errmsg (-1)); 373 return cleanup (-1); 374 } 375 376 /* How many sections are we talking about? */ 377 if (elf_getshdrnum (elf, &shnum) != 0) 378 { 379 error (0, 0, "Couldn't get number of sections in %s: %s", 380 fname, elf_errmsg (1)); 381 return cleanup (-1); 382 } 383 384 if (shnum == 0) 385 { 386 error (0, 0, "ELF file %s has no sections", fname); 387 return cleanup (-1); 388 } 389 390 sections = xcalloc (shnum / 8 + 1, sizeof (unsigned int)); 391 392 size_t phnum; 393 if (elf_getphdrnum (elf, &phnum) != 0) 394 { 395 error (0, 0, "Couldn't get phdrnum: %s", elf_errmsg (-1)); 396 return cleanup (-1); 397 } 398 399 /* Whether we need to adjust any section names (going to/from GNU 400 naming). If so we'll need to build a new section header string 401 table. */ 402 bool adjust_names = false; 403 404 /* If there are phdrs we want to maintain the layout of the 405 allocated sections in the file. */ 406 bool layout = phnum != 0; 407 408 /* While going through all sections keep track of last section data 409 offset if needed to keep the layout. We are responsible for 410 adding the section offsets and headers (e_shoff) in that case 411 (which we will place after the last section). */ 412 GElf_Off last_offset = 0; 413 if (layout) 414 last_offset = (ehdr.e_phoff 415 + gelf_fsize (elf, ELF_T_PHDR, phnum, EV_CURRENT)); 416 417 /* Which section, if any, is a symbol table that shares a string 418 table with the section header string table? */ 419 size_t symtabndx = 0; 420 421 /* We do three passes over all sections. 422 423 First an inspection pass over the old Elf to see which section 424 data needs to be copied and/or transformed, which sections need a 425 names change and whether there is a symbol table that might need 426 to be adjusted be if the section header name table is changed. 427 428 Second a collection pass that creates the Elf sections and copies 429 the data. This pass will compress/decompress section data when 430 needed. And it will collect all data needed if we'll need to 431 construct a new string table. Afterwards the new string table is 432 constructed. 433 434 Third a fixup/adjustment pass over the new Elf that will adjust 435 any section references (names) and adjust the layout based on the 436 new sizes of the sections if necessary. This pass is optional if 437 we aren't responsible for the layout and the section header 438 string table hasn't been changed. */ 439 440 /* Inspection pass. */ 441 size_t maxnamelen = 0; 442 Elf_Scn *scn = NULL; 443 while ((scn = elf_nextscn (elf, scn)) != NULL) 444 { 445 size_t ndx = elf_ndxscn (scn); 446 if (ndx > shnum) 447 { 448 error (0, 0, "Unexpected section number %zd, expected only %zd", 449 ndx, shnum); 450 cleanup (-1); 451 } 452 453 GElf_Shdr shdr_mem; 454 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 455 if (shdr == NULL) 456 { 457 error (0, 0, "Couldn't get shdr for section %zd", ndx); 458 return cleanup (-1); 459 } 460 461 const char *sname = elf_strptr (elf, shdrstrndx, shdr->sh_name); 462 if (sname == NULL) 463 { 464 error (0, 0, "Couldn't get name for section %zd", ndx); 465 return cleanup (-1); 466 } 467 468 if (section_name_matches (sname)) 469 { 470 if (shdr->sh_type != SHT_NOBITS 471 && (shdr->sh_flags & SHF_ALLOC) == 0) 472 { 473 set_section (ndx); 474 /* Check if we might want to change this section name. */ 475 if (! adjust_names 476 && ((type != T_COMPRESS_GNU 477 && strncmp (sname, ".zdebug", 478 strlen (".zdebug")) == 0) 479 || (type == T_COMPRESS_GNU 480 && strncmp (sname, ".debug", 481 strlen (".debug")) == 0))) 482 adjust_names = true; 483 484 /* We need a buffer this large if we change the names. */ 485 if (adjust_names) 486 { 487 size_t slen = strlen (sname); 488 if (slen > maxnamelen) 489 maxnamelen = slen; 490 } 491 } 492 else 493 if (verbose >= 0) 494 printf ("[%zd] %s ignoring %s section\n", ndx, sname, 495 (shdr->sh_type == SHT_NOBITS ? "no bits" : "allocated")); 496 } 497 498 if (shdr->sh_type == SHT_SYMTAB) 499 { 500 /* Check if we might have to adjust the symbol name indexes. */ 501 if (shdr->sh_link == shdrstrndx) 502 { 503 if (symtabndx != 0) 504 { 505 error (0, 0, 506 "Multiple symbol tables (%zd, %zd) using the same string table unsupported", symtabndx, ndx); 507 return cleanup (-1); 508 } 509 symtabndx = ndx; 510 } 511 } 512 513 /* Keep track of last allocated data offset. */ 514 if (layout) 515 if ((shdr->sh_flags & SHF_ALLOC) != 0) 516 { 517 GElf_Off off = shdr->sh_offset + (shdr->sh_type != SHT_NOBITS 518 ? shdr->sh_size : 0); 519 if (last_offset < off) 520 last_offset = off; 521 } 522 } 523 524 if (adjust_names) 525 { 526 names = ebl_strtabinit (true); 527 if (names == NULL) 528 { 529 error (0, 0, "Not enough memory for new strtab"); 530 return cleanup (-1); 531 } 532 scnstrents = xmalloc (shnum 533 * sizeof (struct Ebl_Strent *)); 534 scnnames = xcalloc (shnum, sizeof (char *)); 535 } 536 537 /* Create a new (temporary) ELF file for the result. */ 538 if (foutput == NULL) 539 { 540 size_t fname_len = strlen (fname); 541 fnew = xmalloc (fname_len + sizeof (".XXXXXX")); 542 strcpy (mempcpy (fnew, fname, fname_len), ".XXXXXX"); 543 fdnew = mkstemp (fnew); 544 } 545 else 546 { 547 fnew = xstrdup (foutput); 548 fdnew = open (fnew, O_WRONLY | O_CREAT, st.st_mode & ALLPERMS); 549 } 550 551 if (fdnew < 0) 552 { 553 error (0, errno, "Couldn't create output file %s", fnew); 554 /* Since we didn't create it we don't want to try to unlink it. */ 555 free (fnew); 556 fnew = NULL; 557 return cleanup (-1); 558 } 559 560 elfnew = elf_begin (fdnew, ELF_C_WRITE, NULL); 561 if (elfnew == NULL) 562 { 563 error (0, 0, "Couldn't open new ELF %s for writing: %s", 564 fnew, elf_errmsg (-1)); 565 return cleanup (-1); 566 } 567 568 /* Create the new ELF header and copy over all the data. */ 569 if (gelf_newehdr (elfnew, gelf_getclass (elf)) == 0) 570 { 571 error (0, 0, "Couldn't create new ehdr: %s", elf_errmsg (-1)); 572 return cleanup (-1); 573 } 574 575 GElf_Ehdr newehdr; 576 if (gelf_getehdr (elfnew, &newehdr) == NULL) 577 { 578 error (0, 0, "Couldn't get new ehdr: %s", elf_errmsg (-1)); 579 return cleanup (-1); 580 } 581 582 newehdr.e_ident[EI_DATA] = ehdr.e_ident[EI_DATA]; 583 newehdr.e_type = ehdr.e_type; 584 newehdr.e_machine = ehdr.e_machine; 585 newehdr.e_version = ehdr.e_version; 586 newehdr.e_entry = ehdr.e_entry; 587 newehdr.e_flags = ehdr.e_flags; 588 589 if (gelf_update_ehdr (elfnew, &newehdr) == 0) 590 { 591 error (0, 0, "Couldn't update ehdr: %s", elf_errmsg (-1)); 592 return cleanup (-1); 593 } 594 595 /* Copy over the phdrs as is. */ 596 if (phnum != 0) 597 { 598 if (gelf_newphdr (elfnew, phnum) == 0) 599 { 600 error (0, 0, "Couldn't create phdrs: %s", elf_errmsg (-1)); 601 return cleanup (-1); 602 } 603 604 for (size_t cnt = 0; cnt < phnum; ++cnt) 605 { 606 GElf_Phdr phdr_mem; 607 GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem); 608 if (phdr == NULL) 609 { 610 error (0, 0, "Couldn't get phdr %zd: %s", cnt, elf_errmsg (-1)); 611 return cleanup (-1); 612 } 613 if (gelf_update_phdr (elfnew, cnt, phdr) == 0) 614 { 615 error (0, 0, "Couldn't create phdr %zd: %s", cnt, 616 elf_errmsg (-1)); 617 return cleanup (-1); 618 } 619 } 620 } 621 622 /* Possibly add a 'z' and zero terminator. */ 623 if (maxnamelen > 0) 624 snamebuf = xmalloc (maxnamelen + 2); 625 626 /* We might want to read/adjust the section header strings and 627 symbol tables. If so, and those sections are to be compressed 628 then we will have to decompress it during the collection pass and 629 compress it again in the fixup pass. Don't compress unnecessary 630 and keep track of whether or not to compress them (later in the 631 fixup pass). Also record the original size, so we can report the 632 difference later when we do compress. */ 633 int shstrtab_compressed = T_UNSET; 634 size_t shstrtab_size = 0; 635 char *shstrtab_name = NULL; 636 char *shstrtab_newname = NULL; 637 int symtab_compressed = T_UNSET; 638 size_t symtab_size = 0; 639 char *symtab_name = NULL; 640 char *symtab_newname = NULL; 641 642 /* Collection pass. Copy over the sections, (de)compresses matching 643 sections, collect names of sections and symbol table if 644 necessary. */ 645 scn = NULL; 646 while ((scn = elf_nextscn (elf, scn)) != NULL) 647 { 648 size_t ndx = elf_ndxscn (scn); 649 assert (ndx < shnum); 650 651 /* (de)compress if section matched. */ 652 char *sname = NULL; 653 char *newname = NULL; 654 if (get_section (ndx)) 655 { 656 GElf_Shdr shdr_mem; 657 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 658 if (shdr == NULL) 659 { 660 error (0, 0, "Couldn't get shdr for section %zd", ndx); 661 return cleanup (-1); 662 } 663 664 uint64_t size = shdr->sh_size; 665 sname = elf_strptr (elf, shdrstrndx, shdr->sh_name); 666 if (sname == NULL) 667 { 668 error (0, 0, "Couldn't get name for section %zd", ndx); 669 return cleanup (-1); 670 } 671 672 /* strdup sname, the shdrstrndx section itself might be 673 (de)compressed, invalidating the string pointers. */ 674 sname = xstrdup (sname); 675 676 /* We might want to decompress (and rename), but not 677 compress during this pass since we might need the section 678 data in later passes. Skip those sections for now and 679 compress them in the fixup pass. */ 680 bool skip_compress_section = (adjust_names 681 && (ndx == shdrstrndx 682 || ndx == symtabndx)); 683 684 switch (type) 685 { 686 case T_DECOMPRESS: 687 if ((shdr->sh_flags & SHF_COMPRESSED) != 0) 688 { 689 if (compress_section (scn, size, sname, NULL, ndx, 690 false, false, verbose > 0) < 0) 691 return cleanup (-1); 692 } 693 else if (strncmp (sname, ".zdebug", strlen (".zdebug")) == 0) 694 { 695 snamebuf[0] = '.'; 696 strcpy (&snamebuf[1], &sname[2]); 697 newname = snamebuf; 698 if (compress_section (scn, size, sname, newname, ndx, 699 true, false, verbose > 0) < 0) 700 return cleanup (-1); 701 } 702 else if (verbose > 0) 703 printf ("[%zd] %s already decompressed\n", ndx, sname); 704 break; 705 706 case T_COMPRESS_GNU: 707 if (strncmp (sname, ".debug", strlen (".debug")) == 0) 708 { 709 if ((shdr->sh_flags & SHF_COMPRESSED) != 0) 710 { 711 /* First decompress to recompress GNU style. 712 Don't report even when verbose. */ 713 if (compress_section (scn, size, sname, NULL, ndx, 714 false, false, false) < 0) 715 return cleanup (-1); 716 } 717 718 snamebuf[0] = '.'; 719 snamebuf[1] = 'z'; 720 strcpy (&snamebuf[2], &sname[1]); 721 newname = snamebuf; 722 723 if (skip_compress_section) 724 { 725 if (ndx == shdrstrndx) 726 { 727 shstrtab_size = size; 728 shstrtab_compressed = T_COMPRESS_GNU; 729 shstrtab_name = xstrdup (sname); 730 shstrtab_newname = xstrdup (newname); 731 } 732 else 733 { 734 symtab_size = size; 735 symtab_compressed = T_COMPRESS_GNU; 736 symtab_name = xstrdup (sname); 737 symtab_newname = xstrdup (newname); 738 } 739 } 740 else 741 { 742 int res = compress_section (scn, size, sname, newname, 743 ndx, true, true, 744 verbose > 0); 745 if (res < 0) 746 return cleanup (-1); 747 748 if (res == 0) 749 newname = NULL; 750 } 751 } 752 else if (verbose >= 0) 753 { 754 if (strncmp (sname, ".zdebug", strlen (".zdebug")) == 0) 755 printf ("[%zd] %s unchanged, already GNU compressed", 756 ndx, sname); 757 else 758 printf ("[%zd] %s cannot GNU compress section not starting with .debug\n", 759 ndx, sname); 760 } 761 break; 762 763 case T_COMPRESS_ZLIB: 764 if ((shdr->sh_flags & SHF_COMPRESSED) == 0) 765 { 766 if (strncmp (sname, ".zdebug", strlen (".zdebug")) == 0) 767 { 768 /* First decompress to recompress zlib style. 769 Don't report even when verbose. */ 770 if (compress_section (scn, size, sname, NULL, ndx, 771 true, false, false) < 0) 772 return cleanup (-1); 773 774 snamebuf[0] = '.'; 775 strcpy (&snamebuf[1], &sname[2]); 776 newname = snamebuf; 777 } 778 779 if (skip_compress_section) 780 { 781 if (ndx == shdrstrndx) 782 { 783 shstrtab_size = size; 784 shstrtab_compressed = T_COMPRESS_ZLIB; 785 shstrtab_name = xstrdup (sname); 786 shstrtab_newname = (newname == NULL 787 ? NULL : xstrdup (newname)); 788 } 789 else 790 { 791 symtab_size = size; 792 symtab_compressed = T_COMPRESS_ZLIB; 793 symtab_name = xstrdup (sname); 794 symtab_newname = (newname == NULL 795 ? NULL : xstrdup (newname)); 796 } 797 } 798 else if (compress_section (scn, size, sname, newname, ndx, 799 false, true, verbose > 0) < 0) 800 return cleanup (-1); 801 } 802 else if (verbose > 0) 803 printf ("[%zd] %s already compressed\n", ndx, sname); 804 break; 805 } 806 807 free (sname); 808 } 809 810 Elf_Scn *newscn = elf_newscn (elfnew); 811 if (newscn == NULL) 812 { 813 error (0, 0, "Couldn't create new section %zd", ndx); 814 return cleanup (-1); 815 } 816 817 GElf_Shdr shdr_mem; 818 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 819 if (shdr == NULL) 820 { 821 error (0, 0, "Couldn't get shdr for section %zd", ndx); 822 return cleanup (-1); 823 } 824 825 if (gelf_update_shdr (newscn, shdr) == 0) 826 { 827 error (0, 0, "Couldn't update section header %zd", ndx); 828 return cleanup (-1); 829 } 830 831 /* Except for the section header string table all data can be 832 copied as is. The section header string table will be 833 created later and the symbol table might be fixed up if 834 necessary. */ 835 if (! adjust_names || ndx != shdrstrndx) 836 { 837 Elf_Data *data = elf_getdata (scn, NULL); 838 if (data == NULL) 839 { 840 error (0, 0, "Couldn't get data from section %zd", ndx); 841 return cleanup (-1); 842 } 843 844 Elf_Data *newdata = elf_newdata (newscn); 845 if (newdata == NULL) 846 { 847 error (0, 0, "Couldn't create new data for section %zd", ndx); 848 return cleanup (-1); 849 } 850 851 *newdata = *data; 852 } 853 854 /* Keep track of the (new) section names. */ 855 if (adjust_names) 856 { 857 char *name; 858 if (newname != NULL) 859 name = newname; 860 else 861 { 862 name = elf_strptr (elf, shdrstrndx, shdr->sh_name); 863 if (name == NULL) 864 { 865 error (0, 0, "Couldn't get name for section [%zd]", ndx); 866 return cleanup (-1); 867 } 868 } 869 870 /* We need to keep a copy of the name till the strtab is done. */ 871 name = scnnames[ndx] = xstrdup (name); 872 if ((scnstrents[ndx] = ebl_strtabadd (names, name, 0)) == NULL) 873 { 874 error (0, 0, "No memory to add section name string table"); 875 return cleanup (-1); 876 } 877 878 /* If the symtab shares strings then add those too. */ 879 if (ndx == symtabndx) 880 { 881 /* If the section is (still) compressed we'll need to 882 uncompress it first to adjust the data, then 883 recompress it in the fixup pass. */ 884 if (symtab_compressed == T_UNSET) 885 { 886 size_t size = shdr->sh_size; 887 if ((shdr->sh_flags == SHF_COMPRESSED) != 0) 888 { 889 /* Don't report the (internal) uncompression. */ 890 if (compress_section (newscn, size, sname, NULL, ndx, 891 false, false, false) < 0) 892 return cleanup (-1); 893 894 symtab_size = size; 895 symtab_compressed = T_COMPRESS_ZLIB; 896 } 897 else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0) 898 { 899 /* Don't report the (internal) uncompression. */ 900 if (compress_section (newscn, size, sname, NULL, ndx, 901 true, false, false) < 0) 902 return cleanup (-1); 903 904 symtab_size = size; 905 symtab_compressed = T_COMPRESS_GNU; 906 } 907 } 908 909 Elf_Data *symd = elf_getdata (newscn, NULL); 910 if (symd == NULL) 911 { 912 error (0, 0, "Couldn't get symtab data for section [%zd] %s", 913 ndx, name); 914 return cleanup (-1); 915 } 916 size_t elsize = gelf_fsize (elfnew, ELF_T_SYM, 1, EV_CURRENT); 917 size_t syms = symd->d_size / elsize; 918 symstrents = xmalloc (syms * sizeof (struct Ebl_Strent *)); 919 for (size_t i = 0; i < syms; i++) 920 { 921 GElf_Sym sym_mem; 922 GElf_Sym *sym = gelf_getsym (symd, i, &sym_mem); 923 if (sym == NULL) 924 { 925 error (0, 0, "Couldn't get symbol %zd", i); 926 return cleanup (-1); 927 } 928 if (sym->st_name != 0) 929 { 930 /* Note we take the name from the original ELF, 931 since the new one will not have setup the 932 strtab yet. */ 933 const char *symname = elf_strptr (elf, shdrstrndx, 934 sym->st_name); 935 if (symname == NULL) 936 { 937 error (0, 0, "Couldn't get symbol %zd name", i); 938 return cleanup (-1); 939 } 940 symstrents[i] = ebl_strtabadd (names, symname, 0); 941 if (symstrents[i] == NULL) 942 { 943 error (0, 0, "No memory to add to symbol name"); 944 return cleanup (-1); 945 } 946 } 947 } 948 } 949 } 950 } 951 952 if (adjust_names) 953 { 954 /* We got all needed strings, put the new data in the shstrtab. */ 955 if (verbose > 0) 956 printf ("[%zd] Updating section string table\n", shdrstrndx); 957 958 scn = elf_getscn (elfnew, shdrstrndx); 959 if (scn == NULL) 960 { 961 error (0, 0, "Couldn't get new section header string table [%zd]", 962 shdrstrndx); 963 return cleanup (-1); 964 } 965 966 Elf_Data *data = elf_newdata (scn); 967 if (data == NULL) 968 { 969 error (0, 0, "Couldn't create new section header string table data"); 970 return cleanup (-1); 971 } 972 ebl_strtabfinalize (names, data); 973 namesbuf = data->d_buf; 974 975 GElf_Shdr shdr_mem; 976 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 977 if (shdr == NULL) 978 { 979 error (0, 0, "Couldn't get shdr for new section strings %zd", 980 shdrstrndx); 981 return cleanup (-1); 982 } 983 984 /* Note that we also might have to compress and possibly set 985 sh_off below */ 986 shdr->sh_name = ebl_strtaboffset (scnstrents[shdrstrndx]); 987 shdr->sh_type = SHT_STRTAB; 988 shdr->sh_flags = 0; 989 shdr->sh_addr = 0; 990 shdr->sh_offset = 0; 991 shdr->sh_size = data->d_size; 992 shdr->sh_link = SHN_UNDEF; 993 shdr->sh_info = SHN_UNDEF; 994 shdr->sh_addralign = 1; 995 shdr->sh_entsize = 0; 996 997 if (gelf_update_shdr (scn, shdr) == 0) 998 { 999 error (0, 0, "Couldn't update new section strings [%zd]", 1000 shdrstrndx); 1001 return cleanup (-1); 1002 } 1003 1004 /* We might have to compress the data if the user asked us to, 1005 or if the section was already compressed (and the user didn't 1006 ask for decompression). Note somewhat identical code for 1007 symtab below. */ 1008 if (shstrtab_compressed == T_UNSET) 1009 { 1010 /* The user didn't ask for compression, but maybe it was 1011 compressed in the original ELF file. */ 1012 Elf_Scn *oldscn = elf_getscn (elf, shdrstrndx); 1013 if (oldscn == NULL) 1014 { 1015 error (0, 0, "Couldn't get section header string table [%zd]", 1016 shdrstrndx); 1017 return cleanup (-1); 1018 } 1019 1020 shdr = gelf_getshdr (oldscn, &shdr_mem); 1021 if (shdr == NULL) 1022 { 1023 error (0, 0, "Couldn't get shdr for old section strings [%zd]", 1024 shdrstrndx); 1025 return cleanup (-1); 1026 } 1027 1028 shstrtab_name = elf_strptr (elf, shdrstrndx, shdr->sh_name); 1029 if (shstrtab_name == NULL) 1030 { 1031 error (0, 0, "Couldn't get name for old section strings [%zd]", 1032 shdrstrndx); 1033 return cleanup (-1); 1034 } 1035 1036 shstrtab_size = shdr->sh_size; 1037 if ((shdr->sh_flags & SHF_COMPRESSED) != 0) 1038 shstrtab_compressed = T_COMPRESS_ZLIB; 1039 else if (strncmp (shstrtab_name, ".zdebug", strlen (".zdebug")) == 0) 1040 shstrtab_compressed = T_COMPRESS_GNU; 1041 } 1042 1043 /* Should we (re)compress? */ 1044 if (shstrtab_compressed != T_UNSET) 1045 { 1046 if (compress_section (scn, shstrtab_size, shstrtab_name, 1047 shstrtab_newname, shdrstrndx, 1048 shstrtab_compressed == T_COMPRESS_GNU, 1049 true, verbose > 0) < 0) 1050 return cleanup (-1); 1051 } 1052 } 1053 1054 /* Make sure to re-get the new ehdr. Adding phdrs and shdrs will 1055 have changed it. */ 1056 if (gelf_getehdr (elfnew, &newehdr) == NULL) 1057 { 1058 error (0, 0, "Couldn't re-get new ehdr: %s", elf_errmsg (-1)); 1059 return cleanup (-1); 1060 } 1061 1062 /* Set this after the sections have been created, otherwise section 1063 zero might not exist yet. */ 1064 if (setshdrstrndx (elfnew, &newehdr, shdrstrndx) != 0) 1065 { 1066 error (0, 0, "Couldn't set new shdrstrndx: %s", elf_errmsg (-1)); 1067 return cleanup (-1); 1068 } 1069 1070 /* Fixup pass. Adjust string table references, symbol table and 1071 layout if necessary. */ 1072 if (layout || adjust_names) 1073 { 1074 scn = NULL; 1075 while ((scn = elf_nextscn (elfnew, scn)) != NULL) 1076 { 1077 size_t ndx = elf_ndxscn (scn); 1078 1079 GElf_Shdr shdr_mem; 1080 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 1081 if (shdr == NULL) 1082 { 1083 error (0, 0, "Couldn't get shdr for section %zd", ndx); 1084 return cleanup (-1); 1085 } 1086 1087 /* Keep the offset of allocated sections so they are at the 1088 same place in the file. Add (possibly changed) 1089 unallocated ones after the allocated ones. */ 1090 if ((shdr->sh_flags & SHF_ALLOC) == 0) 1091 { 1092 /* Zero means one. No alignment constraints. */ 1093 size_t addralign = shdr->sh_addralign ?: 1; 1094 last_offset = (last_offset + addralign - 1) & ~(addralign - 1); 1095 shdr->sh_offset = last_offset; 1096 if (shdr->sh_type != SHT_NOBITS) 1097 last_offset += shdr->sh_size; 1098 } 1099 1100 if (adjust_names) 1101 shdr->sh_name = ebl_strtaboffset (scnstrents[ndx]); 1102 1103 if (gelf_update_shdr (scn, shdr) == 0) 1104 { 1105 error (0, 0, "Couldn't update section header %zd", ndx); 1106 return cleanup (-1); 1107 } 1108 1109 if (adjust_names && ndx == symtabndx) 1110 { 1111 if (verbose > 0) 1112 printf ("[%zd] Updating symbol table\n", symtabndx); 1113 1114 Elf_Data *symd = elf_getdata (scn, NULL); 1115 if (symd == NULL) 1116 { 1117 error (0, 0, "Couldn't get new symtab data section [%zd]", 1118 ndx); 1119 return cleanup (-1); 1120 } 1121 size_t elsize = gelf_fsize (elfnew, ELF_T_SYM, 1, EV_CURRENT); 1122 size_t syms = symd->d_size / elsize; 1123 for (size_t i = 0; i < syms; i++) 1124 { 1125 GElf_Sym sym_mem; 1126 GElf_Sym *sym = gelf_getsym (symd, i, &sym_mem); 1127 if (sym == NULL) 1128 { 1129 error (0, 0, "2 Couldn't get symbol %zd", i); 1130 return cleanup (-1); 1131 } 1132 1133 if (sym->st_name != 0) 1134 { 1135 sym->st_name = ebl_strtaboffset (symstrents[i]); 1136 1137 if (gelf_update_sym (symd, i, sym) == 0) 1138 { 1139 error (0, 0, "Couldn't update symbol %zd", i); 1140 return cleanup (-1); 1141 } 1142 } 1143 } 1144 1145 /* We might have to compress the data if the user asked 1146 us to, or if the section was already compressed (and 1147 the user didn't ask for decompression). Note 1148 somewhat identical code for shstrtab above. */ 1149 if (symtab_compressed == T_UNSET) 1150 { 1151 /* The user didn't ask for compression, but maybe it was 1152 compressed in the original ELF file. */ 1153 Elf_Scn *oldscn = elf_getscn (elf, symtabndx); 1154 if (oldscn == NULL) 1155 { 1156 error (0, 0, "Couldn't get symbol table [%zd]", 1157 symtabndx); 1158 return cleanup (-1); 1159 } 1160 1161 shdr = gelf_getshdr (oldscn, &shdr_mem); 1162 if (shdr == NULL) 1163 { 1164 error (0, 0, "Couldn't get old symbol table shdr [%zd]", 1165 symtabndx); 1166 return cleanup (-1); 1167 } 1168 1169 symtab_name = elf_strptr (elf, shdrstrndx, shdr->sh_name); 1170 if (symtab_name == NULL) 1171 { 1172 error (0, 0, "Couldn't get old symbol table name [%zd]", 1173 symtabndx); 1174 return cleanup (-1); 1175 } 1176 1177 symtab_size = shdr->sh_size; 1178 if ((shdr->sh_flags & SHF_COMPRESSED) != 0) 1179 symtab_compressed = T_COMPRESS_ZLIB; 1180 else if (strncmp (symtab_name, ".zdebug", 1181 strlen (".zdebug")) == 0) 1182 symtab_compressed = T_COMPRESS_GNU; 1183 } 1184 1185 /* Should we (re)compress? */ 1186 if (symtab_compressed != T_UNSET) 1187 { 1188 if (compress_section (scn, symtab_size, symtab_name, 1189 symtab_newname, symtabndx, 1190 symtab_compressed == T_COMPRESS_GNU, 1191 true, verbose > 0) < 0) 1192 return cleanup (-1); 1193 } 1194 } 1195 } 1196 } 1197 1198 /* If we have phdrs we want elf_update to layout the SHF_ALLOC 1199 sections precisely as in the original file. In that case we are 1200 also responsible for setting phoff and shoff */ 1201 if (layout) 1202 { 1203 if (gelf_getehdr (elfnew, &newehdr) == NULL) 1204 { 1205 error (0, 0, "Couldn't get ehdr: %s", elf_errmsg (-1)); 1206 return cleanup (-1); 1207 } 1208 1209 /* Position the shdrs after the last (unallocated) section. */ 1210 const size_t offsize = gelf_fsize (elfnew, ELF_T_OFF, 1, EV_CURRENT); 1211 newehdr.e_shoff = ((last_offset + offsize - 1) 1212 & ~((GElf_Off) (offsize - 1))); 1213 1214 /* The phdrs go in the same place as in the original file. 1215 Normally right after the ELF header. */ 1216 newehdr.e_phoff = ehdr.e_phoff; 1217 1218 if (gelf_update_ehdr (elfnew, &newehdr) == 0) 1219 { 1220 error (0, 0, "Couldn't update ehdr: %s", elf_errmsg (-1)); 1221 return cleanup (-1); 1222 } 1223 } 1224 1225 elf_flagelf (elfnew, ELF_C_SET, ((layout ? ELF_F_LAYOUT : 0) 1226 | (permissive ? ELF_F_PERMISSIVE : 0))); 1227 1228 if (elf_update (elfnew, ELF_C_WRITE) < 0) 1229 { 1230 error (0, 0, "Couldn't write %s: %s", fnew, elf_errmsg (-1)); 1231 return cleanup (-1); 1232 } 1233 1234 elf_end (elfnew); 1235 elfnew = NULL; 1236 1237 /* Try to match mode and owner.group of the original file. */ 1238 if (fchmod (fdnew, st.st_mode & ALLPERMS) != 0) 1239 if (verbose >= 0) 1240 error (0, errno, "Couldn't fchmod %s", fnew); 1241 if (fchown (fdnew, st.st_uid, st.st_gid) != 0) 1242 if (verbose >= 0) 1243 error (0, errno, "Couldn't fchown %s", fnew); 1244 1245 /* Finally replace the old file with the new file. */ 1246 if (foutput == NULL) 1247 if (rename (fnew, fname) != 0) 1248 { 1249 error (0, errno, "Couldn't rename %s to %s", fnew, fname); 1250 return cleanup (-1); 1251 } 1252 1253 /* We are finally done with the new file, don't unlink it now. */ 1254 free (fnew); 1255 fnew = NULL; 1256 1257 return cleanup (0); 1258 } 1259 1260 int 1261 main (int argc, char **argv) 1262 { 1263 const struct argp_option options[] = 1264 { 1265 { "output", 'o', "FILE", 0, 1266 N_("Place (de)compressed output into FILE"), 1267 0 }, 1268 { "type", 't', "TYPE", 0, 1269 N_("What type of compression to apply. TYPE can be 'none' (decompress), 'zlib' (ELF ZLIB compression, the default, 'zlib-gabi' is an alias) or 'zlib-gnu' (.zdebug GNU style compression, 'gnu' is an alias)"), 1270 0 }, 1271 { "name", 'n', "SECTION", 0, 1272 N_("SECTION name to (de)compress, SECTION is an extended wildcard pattern (defaults to '.?(z)debug*')"), 1273 0 }, 1274 { "verbose", 'v', NULL, 0, 1275 N_("Print a message for each section being (de)compressed"), 1276 0 }, 1277 { "force", 'f', NULL, 0, 1278 N_("Force compression of section even if it would become larger"), 1279 0 }, 1280 { "permissive", 'p', NULL, 0, 1281 N_("Relax a few rules to handle slightly broken ELF files"), 1282 0 }, 1283 { "quiet", 'q', NULL, 0, 1284 N_("Be silent when a section cannot be compressed"), 1285 0 }, 1286 { NULL, 0, NULL, 0, NULL, 0 } 1287 }; 1288 1289 const struct argp argp = 1290 { 1291 .options = options, 1292 .parser = parse_opt, 1293 .args_doc = N_("FILE..."), 1294 .doc = N_("Compress or decompress sections in an ELF file.") 1295 }; 1296 1297 int remaining; 1298 if (argp_parse (&argp, argc, argv, 0, &remaining, NULL) != 0) 1299 return EXIT_FAILURE; 1300 1301 /* Should already be handled by ARGP_KEY_NO_ARGS case above, 1302 just sanity check. */ 1303 if (remaining >= argc) 1304 error (EXIT_FAILURE, 0, N_("No input file given")); 1305 1306 /* Likewise for the ARGP_KEY_ARGS case above, an extra sanity check. */ 1307 if (foutput != NULL && remaining + 1 < argc) 1308 error (EXIT_FAILURE, 0, 1309 N_("Only one input file allowed together with '-o'")); 1310 1311 elf_version (EV_CURRENT); 1312 1313 /* Process all the remaining files. */ 1314 int result = 0; 1315 do 1316 result |= process_file (argv[remaining]); 1317 while (++remaining < argc); 1318 1319 free_patterns (); 1320 return result; 1321 } 1322