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