1 /* Compress or decompress an ELF file.
2 Copyright (C) 2015, 2016, 2018 Red Hat, Inc.
3 This file is part of elfutils.
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.
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.
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/>. */
29 #include <sys/types.h>
32 #include ELFUTILS_HEADER(elf)
33 #include ELFUTILS_HEADER(ebl)
34 #include ELFUTILS_HEADER(dwelf)
38 #include "printversion.h"
40 /* Name and version of program. */
41 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
43 /* Bug report address. */
44 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
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;
51 /* Compression algorithm, where all legal values for ch_type
52 (compression algorithm) do match the following enum. */
60 /* Maximal supported ch_type. */
61 MAXIMAL_CH_TYPE = ZSTD,
66 #define WORD_BITS (8U * sizeof (unsigned int))
68 static enum ch_type type = UNSET;
70 struct section_pattern
73 struct section_pattern *next;
76 static struct section_pattern *patterns = NULL;
79 add_pattern (const char *pattern)
81 struct section_pattern *p = xmalloc (sizeof *p);
82 p->pattern = xstrdup (pattern);
90 struct section_pattern *pattern = patterns;
91 while (pattern != NULL)
93 struct section_pattern *p = pattern;
101 parse_opt (int key, char *arg __attribute__ ((unused)),
102 struct argp_state *state __attribute__ ((unused)))
128 argp_error (state, N_("-o option specified twice"));
135 argp_error (state, N_("-t option specified twice"));
137 if (strcmp ("none", arg) == 0)
139 else if (strcmp ("zlib", arg) == 0 || strcmp ("zlib-gabi", arg) == 0)
141 else if (strcmp ("zlib-gnu", arg) == 0 || strcmp ("gnu", arg) == 0)
143 else if (strcmp ("zstd", arg) == 0)
144 #ifdef USE_ZSTD_COMPRESS
147 argp_error (state, N_("ZSTD support is not enabled"));
150 argp_error (state, N_("unknown compression type '%s'"), arg);
153 case ARGP_KEY_SUCCESS:
156 if (patterns == NULL)
157 add_pattern (".?(z)debug*");
160 case ARGP_KEY_NO_ARGS:
161 /* We need at least one input file. */
162 argp_error (state, N_("No input file given"));
166 if (foutput != NULL && state->argc - state->next > 1)
168 N_("Only one input file allowed together with '-o'"));
169 /* We only use this for checking the number of arguments, we don't
170 actually want to consume them. */
173 return ARGP_ERR_UNKNOWN;
179 section_name_matches (const char *name)
181 struct section_pattern *pattern = patterns;
182 while (pattern != NULL)
184 if (fnmatch (pattern->pattern, name, FNM_EXTMATCH) == 0)
186 pattern = pattern->next;
192 setshdrstrndx (Elf *elf, GElf_Ehdr *ehdr, size_t ndx)
194 if (ndx < SHN_LORESERVE)
195 ehdr->e_shstrndx = ndx;
198 ehdr->e_shstrndx = SHN_XINDEX;
199 Elf_Scn *zscn = elf_getscn (elf, 0);
201 GElf_Shdr *zshdr = gelf_getshdr (zscn, &zshdr_mem);
204 zshdr->sh_link = ndx;
205 if (gelf_update_shdr (zscn, zshdr) == 0)
209 if (gelf_update_ehdr (elf, ehdr) == 0)
216 compress_section (Elf_Scn *scn, size_t orig_size, const char *name,
217 const char *newname, size_t ndx,
218 enum ch_type schtype, enum ch_type dchtype,
221 /* We either compress or decompress. */
222 assert (schtype == NONE || dchtype == NONE);
223 bool compress = dchtype != NONE;
226 unsigned int flags = compress && force ? ELF_CHF_FORCE : 0;
227 if (schtype == ZLIB_GNU || dchtype == ZLIB_GNU)
228 res = elf_compress_gnu (scn, compress ? 1 : 0, flags);
230 res = elf_compress (scn, dchtype, flags);
233 error (0, 0, "Couldn't %s section [%zd] %s: %s",
234 compress ? "compress" : "decompress",
235 ndx, name, elf_errmsg (-1));
238 if (compress && res == 0)
241 printf ("[%zd] %s NOT compressed, wouldn't be smaller\n",
245 if (report_verbose && res > 0)
247 printf ("[%zd] %s %s", ndx, name,
248 compress ? "compressed" : "decompressed");
250 printf (" -> %s", newname);
252 /* Reload shdr, it has changed. */
254 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
257 error (0, 0, "Couldn't get shdr for section [%zd]", ndx);
260 float new = shdr->sh_size;
261 float orig = orig_size ?: 1;
262 printf (" (%zu => %" PRIu64 " %.2f%%)\n",
263 orig_size, shdr->sh_size, (new / orig) * 100);
271 set_section (unsigned int *sections, size_t ndx)
273 sections[ndx / WORD_BITS] |= (1U << (ndx % WORD_BITS));
277 get_section (unsigned int *sections, size_t ndx)
279 return (sections[ndx / WORD_BITS] & (1U << (ndx % WORD_BITS))) != 0;
282 /* How many sections are we going to change? */
284 get_sections (unsigned int *sections, size_t shnum)
287 for (size_t i = 0; i < shnum / WORD_BITS + 1; i++)
288 s += __builtin_popcount (sections[i]);
292 /* Return compression type of a given section SHDR. */
295 get_section_chtype (Elf_Scn *scn, GElf_Shdr *shdr, const char *sname,
298 enum ch_type chtype = UNSET;
299 if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
302 if (gelf_getchdr (scn, &chdr) != NULL)
304 chtype = (enum ch_type)chdr.ch_type;
307 error (0, 0, "Compression type for section %zd"
308 " can't be zero ", ndx);
311 else if (chtype > MAXIMAL_CH_TYPE)
313 error (0, 0, "Compression type (%d) for section %zd"
314 " is unsupported ", chtype, ndx);
319 error (0, 0, "Couldn't get chdr for section %zd", ndx);
321 /* Set ZLIB_GNU compression manually for .zdebug* sections. */
322 else if (startswith (sname, ".zdebug"))
331 process_file (const char *fname)
334 printf ("processing: %s\n", fname);
340 /* The output ELF. */
345 /* Buffer for (one) new section name if necessary. */
346 char *snamebuf = NULL;
348 /* String table (and symbol table), if section names need adjusting. */
349 Dwelf_Strtab *names = NULL;
350 Dwelf_Strent **scnstrents = NULL;
351 Dwelf_Strent **symstrents = NULL;
352 char **scnnames = NULL;
354 /* Section data from names. */
355 void *namesbuf = NULL;
357 /* Which sections match and need to be (un)compressed. */
358 unsigned int *sections = NULL;
360 /* How many sections are we talking about? */
364 fd = open (fname, O_RDONLY);
367 error (0, errno, "Couldn't open %s\n", fname);
371 elf = elf_begin (fd, ELF_C_READ, NULL);
374 error (0, 0, "Couldn't open ELF file %s for reading: %s",
375 fname, elf_errmsg (-1));
379 /* We don't handle ar files (or anything else), we probably should. */
380 Elf_Kind kind = elf_kind (elf);
381 if (kind != ELF_K_ELF)
383 if (kind == ELF_K_AR)
384 error (0, 0, "Cannot handle ar files: %s", fname);
386 error (0, 0, "Unknown file type: %s", fname);
391 if (fstat (fd, &st) != 0)
393 error (0, errno, "Couldn't fstat %s", fname);
398 if (gelf_getehdr (elf, &ehdr) == NULL)
400 error (0, 0, "Couldn't get ehdr for %s: %s", fname, elf_errmsg (-1));
404 /* Get the section header string table. */
406 if (elf_getshdrstrndx (elf, &shdrstrndx) != 0)
408 error (0, 0, "Couldn't get section header string table index in %s: %s",
409 fname, elf_errmsg (-1));
413 /* How many sections are we talking about? */
414 if (elf_getshdrnum (elf, &shnum) != 0)
416 error (0, 0, "Couldn't get number of sections in %s: %s",
417 fname, elf_errmsg (1));
423 error (0, 0, "ELF file %s has no sections", fname);
427 sections = xcalloc (shnum / 8 + 1, sizeof (unsigned int));
430 if (elf_getphdrnum (elf, &phnum) != 0)
432 error (0, 0, "Couldn't get phdrnum: %s", elf_errmsg (-1));
436 /* Whether we need to adjust any section names (going to/from GNU
437 naming). If so we'll need to build a new section header string
439 bool adjust_names = false;
441 /* If there are phdrs we want to maintain the layout of the
442 allocated sections in the file. */
443 bool layout = phnum != 0;
445 /* While going through all sections keep track of last section data
446 offset if needed to keep the layout. We are responsible for
447 adding the section offsets and headers (e_shoff) in that case
448 (which we will place after the last section). */
449 GElf_Off last_offset = 0;
451 last_offset = (ehdr.e_phoff
452 + gelf_fsize (elf, ELF_T_PHDR, phnum, EV_CURRENT));
454 /* Which section, if any, is a symbol table that shares a string
455 table with the section header string table? */
456 size_t symtabndx = 0;
458 /* We do three passes over all sections.
460 First an inspection pass over the old Elf to see which section
461 data needs to be copied and/or transformed, which sections need a
462 names change and whether there is a symbol table that might need
463 to be adjusted be if the section header name table is changed.
465 If nothing needs changing, and the input and output file are the
468 Second a collection pass that creates the Elf sections and copies
469 the data. This pass will compress/decompress section data when
470 needed. And it will collect all data needed if we'll need to
471 construct a new string table. Afterwards the new string table is
474 Third a fixup/adjustment pass over the new Elf that will adjust
475 any section references (names) and adjust the layout based on the
476 new sizes of the sections if necessary. This pass is optional if
477 we aren't responsible for the layout and the section header
478 string table hasn't been changed. */
480 /* Inspection pass. */
481 size_t maxnamelen = 0;
483 while ((scn = elf_nextscn (elf, scn)) != NULL)
485 size_t ndx = elf_ndxscn (scn);
488 error (0, 0, "Unexpected section number %zd, expected only %zd",
494 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
497 error (0, 0, "Couldn't get shdr for section %zd", ndx);
501 const char *sname = elf_strptr (elf, shdrstrndx, shdr->sh_name);
504 error (0, 0, "Couldn't get name for section %zd", ndx);
508 if (section_name_matches (sname))
510 enum ch_type schtype = get_section_chtype (scn, shdr, sname, ndx);
511 if (!force && verbose > 0)
513 /* The current compression matches the final one. */
518 printf ("[%zd] %s already decompressed\n", ndx, sname);
522 printf ("[%zd] %s already compressed\n", ndx, sname);
525 printf ("[%zd] %s already GNU compressed\n", ndx, sname);
532 if (shdr->sh_type != SHT_NOBITS
533 && (shdr->sh_flags & SHF_ALLOC) == 0)
535 set_section (sections, ndx);
536 /* Check if we might want to change this section name. */
538 && ((type != ZLIB_GNU
539 && startswith (sname, ".zdebug"))
541 && startswith (sname, ".debug"))))
544 /* We need a buffer this large if we change the names. */
547 size_t slen = strlen (sname);
548 if (slen > maxnamelen)
554 printf ("[%zd] %s ignoring %s section\n", ndx, sname,
555 (shdr->sh_type == SHT_NOBITS ? "no bits" : "allocated"));
558 if (shdr->sh_type == SHT_SYMTAB)
560 /* Check if we might have to adjust the symbol name indexes. */
561 if (shdr->sh_link == shdrstrndx)
566 "Multiple symbol tables (%zd, %zd) using the same string table unsupported", symtabndx, ndx);
573 /* Keep track of last allocated data offset. */
575 if ((shdr->sh_flags & SHF_ALLOC) != 0)
577 GElf_Off off = shdr->sh_offset + (shdr->sh_type != SHT_NOBITS
578 ? shdr->sh_size : 0);
579 if (last_offset < off)
584 if (foutput == NULL && get_sections (sections, shnum) == 0)
587 printf ("Nothing to do.\n");
594 names = dwelf_strtab_init (true);
597 error (0, 0, "Not enough memory for new strtab");
600 scnstrents = xmalloc (shnum
601 * sizeof (Dwelf_Strent *));
602 scnnames = xcalloc (shnum, sizeof (char *));
605 /* Create a new (temporary) ELF file for the result. */
608 size_t fname_len = strlen (fname);
609 fnew = xmalloc (fname_len + sizeof (".XXXXXX"));
610 strcpy (mempcpy (fnew, fname, fname_len), ".XXXXXX");
611 fdnew = mkstemp (fnew);
615 fnew = xstrdup (foutput);
616 fdnew = open (fnew, O_WRONLY | O_CREAT, st.st_mode & ALLPERMS);
621 error (0, errno, "Couldn't create output file %s", fnew);
622 /* Since we didn't create it we don't want to try to unlink it. */
628 elfnew = elf_begin (fdnew, ELF_C_WRITE, NULL);
631 error (0, 0, "Couldn't open new ELF %s for writing: %s",
632 fnew, elf_errmsg (-1));
636 /* Create the new ELF header and copy over all the data. */
637 if (gelf_newehdr (elfnew, gelf_getclass (elf)) == 0)
639 error (0, 0, "Couldn't create new ehdr: %s", elf_errmsg (-1));
644 if (gelf_getehdr (elfnew, &newehdr) == NULL)
646 error (0, 0, "Couldn't get new ehdr: %s", elf_errmsg (-1));
650 newehdr.e_ident[EI_DATA] = ehdr.e_ident[EI_DATA];
651 newehdr.e_type = ehdr.e_type;
652 newehdr.e_machine = ehdr.e_machine;
653 newehdr.e_version = ehdr.e_version;
654 newehdr.e_entry = ehdr.e_entry;
655 newehdr.e_flags = ehdr.e_flags;
657 if (gelf_update_ehdr (elfnew, &newehdr) == 0)
659 error (0, 0, "Couldn't update ehdr: %s", elf_errmsg (-1));
663 /* Copy over the phdrs as is. */
666 if (gelf_newphdr (elfnew, phnum) == 0)
668 error (0, 0, "Couldn't create phdrs: %s", elf_errmsg (-1));
672 for (size_t cnt = 0; cnt < phnum; ++cnt)
675 GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
678 error (0, 0, "Couldn't get phdr %zd: %s", cnt, elf_errmsg (-1));
681 if (gelf_update_phdr (elfnew, cnt, phdr) == 0)
683 error (0, 0, "Couldn't create phdr %zd: %s", cnt,
690 /* Possibly add a 'z' and zero terminator. */
692 snamebuf = xmalloc (maxnamelen + 2);
694 /* We might want to read/adjust the section header strings and
695 symbol tables. If so, and those sections are to be compressed
696 then we will have to decompress it during the collection pass and
697 compress it again in the fixup pass. Don't compress unnecessary
698 and keep track of whether or not to compress them (later in the
699 fixup pass). Also record the original size, so we can report the
700 difference later when we do compress. */
701 enum ch_type shstrtab_compressed = UNSET;
702 size_t shstrtab_size = 0;
703 char *shstrtab_name = NULL;
704 char *shstrtab_newname = NULL;
705 enum ch_type symtab_compressed = UNSET;
706 size_t symtab_size = 0;
707 char *symtab_name = NULL;
708 char *symtab_newname = NULL;
710 /* Collection pass. Copy over the sections, (de)compresses matching
711 sections, collect names of sections and symbol table if
714 while ((scn = elf_nextscn (elf, scn)) != NULL)
716 size_t ndx = elf_ndxscn (scn);
717 assert (ndx < shnum);
719 /* (de)compress if section matched. */
721 char *newname = NULL;
722 if (get_section (sections, ndx))
725 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
728 error (0, 0, "Couldn't get shdr for section %zd", ndx);
732 uint64_t size = shdr->sh_size;
733 sname = elf_strptr (elf, shdrstrndx, shdr->sh_name);
736 error (0, 0, "Couldn't get name for section %zd", ndx);
740 /* strdup sname, the shdrstrndx section itself might be
741 (de)compressed, invalidating the string pointers. */
742 sname = xstrdup (sname);
745 /* Detect source compression that is how is the section compressed
747 enum ch_type schtype = get_section_chtype (scn, shdr, sname, ndx);
748 if (schtype == UNSET)
751 /* We might want to decompress (and rename), but not
752 compress during this pass since we might need the section
753 data in later passes. Skip those sections for now and
754 compress them in the fixup pass. */
755 bool skip_compress_section = (adjust_names
756 && (ndx == shdrstrndx
757 || ndx == symtabndx));
764 if (schtype == ZLIB_GNU)
767 strcpy (&snamebuf[1], &sname[2]);
770 if (compress_section (scn, size, sname, NULL, ndx,
771 schtype, NONE, verbose > 0) < 0)
774 else if (verbose > 0)
775 printf ("[%zd] %s already decompressed\n", ndx, sname);
779 if (startswith (sname, ".debug"))
781 if (schtype == ZLIB || schtype == ZSTD)
783 /* First decompress to recompress GNU style.
784 Don't report even when verbose. */
785 if (compress_section (scn, size, sname, NULL, ndx,
786 schtype, NONE, false) < 0)
792 strcpy (&snamebuf[2], &sname[1]);
795 if (skip_compress_section)
797 if (ndx == shdrstrndx)
799 shstrtab_size = size;
800 shstrtab_compressed = ZLIB_GNU;
801 if (shstrtab_name != NULL
802 || shstrtab_newname != NULL)
804 error (0, 0, "Internal error,"
805 " shstrtab_name already set,"
806 " while handling section [%zd] %s",
810 shstrtab_name = xstrdup (sname);
811 shstrtab_newname = xstrdup (newname);
816 symtab_compressed = ZLIB_GNU;
817 symtab_name = xstrdup (sname);
818 symtab_newname = xstrdup (newname);
823 int result = compress_section (scn, size, sname, newname,
833 else if (verbose >= 0)
835 if (schtype == ZLIB_GNU)
836 printf ("[%zd] %s unchanged, already GNU compressed\n",
839 printf ("[%zd] %s cannot GNU compress section not starting with .debug\n",
850 /* Decompress first. */
851 if (compress_section (scn, size, sname, NULL, ndx,
852 schtype, NONE, false) < 0)
855 if (schtype == ZLIB_GNU)
858 strcpy (&snamebuf[1], &sname[2]);
863 if (skip_compress_section)
865 if (ndx == shdrstrndx)
867 shstrtab_size = size;
868 shstrtab_compressed = type;
869 if (shstrtab_name != NULL
870 || shstrtab_newname != NULL)
872 error (0, 0, "Internal error,"
873 " shstrtab_name already set,"
874 " while handling section [%zd] %s",
878 shstrtab_name = xstrdup (sname);
879 shstrtab_newname = (newname == NULL
880 ? NULL : xstrdup (newname));
885 symtab_compressed = type;
886 symtab_name = xstrdup (sname);
887 symtab_newname = (newname == NULL
888 ? NULL : xstrdup (newname));
891 else if (compress_section (scn, size, sname, newname, ndx,
892 NONE, type, verbose > 0) < 0)
895 else if (verbose > 0)
896 printf ("[%zd] %s already compressed\n", ndx, sname);
906 Elf_Scn *newscn = elf_newscn (elfnew);
909 error (0, 0, "Couldn't create new section %zd", ndx);
914 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
917 error (0, 0, "Couldn't get shdr for section %zd", ndx);
921 if (gelf_update_shdr (newscn, shdr) == 0)
923 error (0, 0, "Couldn't update section header %zd", ndx);
927 /* Except for the section header string table all data can be
928 copied as is. The section header string table will be
929 created later and the symbol table might be fixed up if
931 if (! adjust_names || ndx != shdrstrndx)
933 Elf_Data *data = elf_getdata (scn, NULL);
936 error (0, 0, "Couldn't get data from section %zd", ndx);
940 Elf_Data *newdata = elf_newdata (newscn);
943 error (0, 0, "Couldn't create new data for section %zd", ndx);
950 /* Keep track of the (new) section names. */
958 name = elf_strptr (elf, shdrstrndx, shdr->sh_name);
961 error (0, 0, "Couldn't get name for section [%zd]", ndx);
966 /* We need to keep a copy of the name till the strtab is done. */
967 name = scnnames[ndx] = xstrdup (name);
968 if ((scnstrents[ndx] = dwelf_strtab_add (names, name)) == NULL)
970 error (0, 0, "No memory to add section name string table");
974 /* If the symtab shares strings then add those too. */
975 if (ndx == symtabndx)
977 /* If the section is (still) compressed we'll need to
978 uncompress it first to adjust the data, then
979 recompress it in the fixup pass. */
980 if (symtab_compressed == UNSET)
982 size_t size = shdr->sh_size;
983 if ((shdr->sh_flags == SHF_COMPRESSED) != 0)
985 /* Don't report the (internal) uncompression. */
986 if (compress_section (newscn, size, sname, NULL, ndx,
987 ZLIB, NONE, false) < 0)
991 symtab_compressed = ZLIB;
993 else if (startswith (name, ".zdebug"))
995 /* Don't report the (internal) uncompression. */
996 if (compress_section (newscn, size, sname, NULL, ndx,
997 ZLIB_GNU, NONE, false) < 0)
1001 symtab_compressed = ZLIB_GNU;
1005 Elf_Data *symd = elf_getdata (newscn, NULL);
1008 error (0, 0, "Couldn't get symtab data for section [%zd] %s",
1012 size_t elsize = gelf_fsize (elfnew, ELF_T_SYM, 1, EV_CURRENT);
1013 size_t syms = symd->d_size / elsize;
1014 if (symstrents != NULL)
1016 error (0, 0, "Internal error, symstrents already set,"
1017 " while handling section [%zd] %s", ndx, name);
1020 symstrents = xmalloc (syms * sizeof (Dwelf_Strent *));
1021 for (size_t i = 0; i < syms; i++)
1024 GElf_Sym *sym = gelf_getsym (symd, i, &sym_mem);
1027 error (0, 0, "Couldn't get symbol %zd", i);
1030 if (sym->st_name != 0)
1032 /* Note we take the name from the original ELF,
1033 since the new one will not have setup the
1035 const char *symname = elf_strptr (elf, shdrstrndx,
1037 if (symname == NULL)
1039 error (0, 0, "Couldn't get symbol %zd name", i);
1042 symstrents[i] = dwelf_strtab_add (names, symname);
1043 if (symstrents[i] == NULL)
1045 error (0, 0, "No memory to add to symbol name");
1056 /* We got all needed strings, put the new data in the shstrtab. */
1058 printf ("[%zd] Updating section string table\n", shdrstrndx);
1060 scn = elf_getscn (elfnew, shdrstrndx);
1063 error (0, 0, "Couldn't get new section header string table [%zd]",
1068 Elf_Data *data = elf_newdata (scn);
1071 error (0, 0, "Couldn't create new section header string table data");
1074 if (dwelf_strtab_finalize (names, data) == NULL)
1076 error (0, 0, "Not enough memory to create string table");
1079 namesbuf = data->d_buf;
1082 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1085 error (0, 0, "Couldn't get shdr for new section strings %zd",
1090 /* Note that we also might have to compress and possibly set
1092 shdr->sh_name = dwelf_strent_off (scnstrents[shdrstrndx]);
1093 shdr->sh_type = SHT_STRTAB;
1096 shdr->sh_offset = 0;
1097 shdr->sh_size = data->d_size;
1098 shdr->sh_link = SHN_UNDEF;
1099 shdr->sh_info = SHN_UNDEF;
1100 shdr->sh_addralign = 1;
1101 shdr->sh_entsize = 0;
1103 if (gelf_update_shdr (scn, shdr) == 0)
1105 error (0, 0, "Couldn't update new section strings [%zd]",
1110 /* We might have to compress the data if the user asked us to,
1111 or if the section was already compressed (and the user didn't
1112 ask for decompression). Note somewhat identical code for
1114 if (shstrtab_compressed == UNSET)
1116 /* The user didn't ask for compression, but maybe it was
1117 compressed in the original ELF file. */
1118 Elf_Scn *oldscn = elf_getscn (elf, shdrstrndx);
1121 error (0, 0, "Couldn't get section header string table [%zd]",
1126 shdr = gelf_getshdr (oldscn, &shdr_mem);
1129 error (0, 0, "Couldn't get shdr for old section strings [%zd]",
1134 shstrtab_name = elf_strptr (elf, shdrstrndx, shdr->sh_name);
1135 if (shstrtab_name == NULL)
1137 error (0, 0, "Couldn't get name for old section strings [%zd]",
1142 shstrtab_size = shdr->sh_size;
1143 if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1144 shstrtab_compressed = ZLIB;
1145 else if (startswith (shstrtab_name, ".zdebug"))
1146 shstrtab_compressed = ZLIB_GNU;
1149 /* Should we (re)compress? */
1150 if (shstrtab_compressed != UNSET)
1152 if (compress_section (scn, shstrtab_size, shstrtab_name,
1153 shstrtab_newname, shdrstrndx,
1154 NONE, shstrtab_compressed,
1160 /* Make sure to re-get the new ehdr. Adding phdrs and shdrs will
1162 if (gelf_getehdr (elfnew, &newehdr) == NULL)
1164 error (0, 0, "Couldn't re-get new ehdr: %s", elf_errmsg (-1));
1168 /* Set this after the sections have been created, otherwise section
1169 zero might not exist yet. */
1170 if (setshdrstrndx (elfnew, &newehdr, shdrstrndx) != 0)
1172 error (0, 0, "Couldn't set new shdrstrndx: %s", elf_errmsg (-1));
1176 /* Fixup pass. Adjust string table references, symbol table and
1177 layout if necessary. */
1178 if (layout || adjust_names)
1181 while ((scn = elf_nextscn (elfnew, scn)) != NULL)
1183 size_t ndx = elf_ndxscn (scn);
1186 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1189 error (0, 0, "Couldn't get shdr for section %zd", ndx);
1193 /* Keep the offset of allocated sections so they are at the
1194 same place in the file. Add (possibly changed)
1195 unallocated ones after the allocated ones. */
1196 if ((shdr->sh_flags & SHF_ALLOC) == 0)
1198 /* Zero means one. No alignment constraints. */
1199 size_t addralign = shdr->sh_addralign ?: 1;
1200 last_offset = (last_offset + addralign - 1) & ~(addralign - 1);
1201 shdr->sh_offset = last_offset;
1202 if (shdr->sh_type != SHT_NOBITS)
1203 last_offset += shdr->sh_size;
1207 shdr->sh_name = dwelf_strent_off (scnstrents[ndx]);
1209 if (gelf_update_shdr (scn, shdr) == 0)
1211 error (0, 0, "Couldn't update section header %zd", ndx);
1215 if (adjust_names && ndx == symtabndx)
1218 printf ("[%zd] Updating symbol table\n", symtabndx);
1220 Elf_Data *symd = elf_getdata (scn, NULL);
1223 error (0, 0, "Couldn't get new symtab data section [%zd]",
1227 size_t elsize = gelf_fsize (elfnew, ELF_T_SYM, 1, EV_CURRENT);
1228 size_t syms = symd->d_size / elsize;
1229 for (size_t i = 0; i < syms; i++)
1232 GElf_Sym *sym = gelf_getsym (symd, i, &sym_mem);
1235 error (0, 0, "2 Couldn't get symbol %zd", i);
1239 if (sym->st_name != 0)
1241 sym->st_name = dwelf_strent_off (symstrents[i]);
1243 if (gelf_update_sym (symd, i, sym) == 0)
1245 error (0, 0, "Couldn't update symbol %zd", i);
1251 /* We might have to compress the data if the user asked
1252 us to, or if the section was already compressed (and
1253 the user didn't ask for decompression). Note
1254 somewhat identical code for shstrtab above. */
1255 if (symtab_compressed == UNSET)
1257 /* The user didn't ask for compression, but maybe it was
1258 compressed in the original ELF file. */
1259 Elf_Scn *oldscn = elf_getscn (elf, symtabndx);
1262 error (0, 0, "Couldn't get symbol table [%zd]",
1267 shdr = gelf_getshdr (oldscn, &shdr_mem);
1270 error (0, 0, "Couldn't get old symbol table shdr [%zd]",
1275 symtab_name = elf_strptr (elf, shdrstrndx, shdr->sh_name);
1276 if (symtab_name == NULL)
1278 error (0, 0, "Couldn't get old symbol table name [%zd]",
1283 symtab_size = shdr->sh_size;
1284 if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1285 symtab_compressed = ZLIB;
1286 else if (startswith (symtab_name, ".zdebug"))
1287 symtab_compressed = ZLIB_GNU;
1290 /* Should we (re)compress? */
1291 if (symtab_compressed != UNSET)
1293 if (compress_section (scn, symtab_size, symtab_name,
1294 symtab_newname, symtabndx,
1295 NONE, symtab_compressed,
1303 /* If we have phdrs we want elf_update to layout the SHF_ALLOC
1304 sections precisely as in the original file. In that case we are
1305 also responsible for setting phoff and shoff */
1308 if (gelf_getehdr (elfnew, &newehdr) == NULL)
1310 error (0, 0, "Couldn't get ehdr: %s", elf_errmsg (-1));
1314 /* Position the shdrs after the last (unallocated) section. */
1315 const size_t offsize = gelf_fsize (elfnew, ELF_T_OFF, 1, EV_CURRENT);
1316 newehdr.e_shoff = ((last_offset + offsize - 1)
1317 & ~((GElf_Off) (offsize - 1)));
1319 /* The phdrs go in the same place as in the original file.
1320 Normally right after the ELF header. */
1321 newehdr.e_phoff = ehdr.e_phoff;
1323 if (gelf_update_ehdr (elfnew, &newehdr) == 0)
1325 error (0, 0, "Couldn't update ehdr: %s", elf_errmsg (-1));
1330 elf_flagelf (elfnew, ELF_C_SET, ((layout ? ELF_F_LAYOUT : 0)
1331 | (permissive ? ELF_F_PERMISSIVE : 0)));
1333 if (elf_update (elfnew, ELF_C_WRITE) < 0)
1335 error (0, 0, "Couldn't write %s: %s", fnew, elf_errmsg (-1));
1342 /* Try to match mode and owner.group of the original file.
1343 Note to set suid bits we have to make sure the owner is setup
1344 correctly first. Otherwise fchmod will drop them silently
1345 or fchown may clear them. */
1346 if (fchown (fdnew, st.st_uid, st.st_gid) != 0)
1348 error (0, errno, "Couldn't fchown %s", fnew);
1349 if (fchmod (fdnew, st.st_mode & ALLPERMS) != 0)
1351 error (0, errno, "Couldn't fchmod %s", fnew);
1353 /* Finally replace the old file with the new file. */
1354 if (foutput == NULL)
1355 if (rename (fnew, fname) != 0)
1357 error (0, errno, "Couldn't rename %s to %s", fnew, fname);
1361 /* We are finally done with the new file, don't unlink it now. */
1383 dwelf_strtab_free (names);
1387 if (scnnames != NULL)
1389 for (size_t n = 0; n < shnum; n++)
1400 main (int argc, char **argv)
1402 const struct argp_option options[] =
1404 { "output", 'o', "FILE", 0,
1405 N_("Place (de)compressed output into FILE"),
1407 { "type", 't', "TYPE", 0,
1408 N_("What type of compression to apply. TYPE can be 'none' (decompress), 'zlib' (ELF ZLIB compression, the default, 'zlib-gabi' is an alias), "
1409 "'zlib-gnu' (.zdebug GNU style compression, 'gnu' is an alias) or 'zstd' (ELF ZSTD compression)"),
1411 { "name", 'n', "SECTION", 0,
1412 N_("SECTION name to (de)compress, SECTION is an extended wildcard pattern (defaults to '.?(z)debug*')"),
1414 { "verbose", 'v', NULL, 0,
1415 N_("Print a message for each section being (de)compressed"),
1417 { "force", 'f', NULL, 0,
1418 N_("Force compression of section even if it would become larger or update/rewrite the file even if no section would be (de)compressed"),
1420 { "permissive", 'p', NULL, 0,
1421 N_("Relax a few rules to handle slightly broken ELF files"),
1423 { "quiet", 'q', NULL, 0,
1424 N_("Be silent when a section cannot be compressed"),
1426 { NULL, 0, NULL, 0, NULL, 0 }
1429 const struct argp argp =
1432 .parser = parse_opt,
1433 .args_doc = N_("FILE..."),
1434 .doc = N_("Compress or decompress sections in an ELF file.")
1438 if (argp_parse (&argp, argc, argv, 0, &remaining, NULL) != 0)
1439 return EXIT_FAILURE;
1441 /* Should already be handled by ARGP_KEY_NO_ARGS case above,
1442 just sanity check. */
1443 if (remaining >= argc)
1444 error_exit (0, N_("No input file given"));
1446 /* Likewise for the ARGP_KEY_ARGS case above, an extra sanity check. */
1447 if (foutput != NULL && remaining + 1 < argc)
1448 error_exit (0, N_("Only one input file allowed together with '-o'"));
1450 elf_version (EV_CURRENT);
1452 /* Process all the remaining files. */
1455 result |= process_file (argv[remaining]);
1456 while (++remaining < argc);