192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard/* Compress or decompress an ELF file. 292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Copyright (C) 2015 Red Hat, Inc. 392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard This file is part of elfutils. 492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard This file is free software; you can redistribute it and/or modify 692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard it under the terms of the GNU General Public License as published by 792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard the Free Software Foundation; either version 3 of the License, or 892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard (at your option) any later version. 992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 1092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard elfutils is distributed in the hope that it will be useful, but 1192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard WITHOUT ANY WARRANTY; without even the implied warranty of 1292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GNU General Public License for more details. 1492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 1592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard You should have received a copy of the GNU General Public License 1692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard along with this program. If not, see <http://www.gnu.org/licenses/>. */ 1792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 1892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include <config.h> 1992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include <assert.h> 2092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include <argp.h> 2192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include <error.h> 2292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include <stdbool.h> 2392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include <stdlib.h> 2492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include <inttypes.h> 2592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include <stdio.h> 2692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include <string.h> 2792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include <locale.h> 2892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include <fcntl.h> 2992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include <fnmatch.h> 3092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include <sys/types.h> 3192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include <sys/stat.h> 3292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include <unistd.h> 3392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include ELFUTILS_HEADER(elf) 3492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include ELFUTILS_HEADER(ebl) 3592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include <gelf.h> 3692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#include "system.h" 3792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 3892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard/* Name and version of program. */ 3992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardstatic void print_version (FILE *stream, struct argp_state *state); 4092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark WielaardARGP_PROGRAM_VERSION_HOOK_DEF = print_version; 4192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 4292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard/* Bug report address. */ 4392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark WielaardARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT; 4492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 4592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardstatic int verbose = 0; /* < 0, no warnings, > 0 extra verbosity. */ 4692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardstatic bool force = false; 4792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardstatic bool permissive = false; 4892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardstatic const char *foutput = NULL; 4992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 5092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#define T_UNSET 0 5192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#define T_DECOMPRESS 1 /* none */ 5292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#define T_COMPRESS_ZLIB 2 /* zlib */ 5392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#define T_COMPRESS_GNU 3 /* zlib-gnu */ 5492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardstatic int type = T_UNSET; 5592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 5692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardstatic void 5792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused))) 5892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard{ 5992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard fprintf (stream, "elfcompress (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); 6092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard} 6192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 6292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardstruct section_pattern 6392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard{ 6492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard char *pattern; 6592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard struct section_pattern *next; 6692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard}; 6792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 6892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardstatic struct section_pattern *patterns = NULL; 6992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 7092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardstatic void 7192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardadd_pattern (const char *pattern) 7292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard{ 7392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard struct section_pattern *p = xmalloc (sizeof *p); 7492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard p->pattern = xstrdup (pattern); 7592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard p->next = patterns; 7692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard patterns = p; 7792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard} 7892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 7992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardstatic void 8092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardfree_patterns (void) 8192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard{ 8292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard struct section_pattern *pattern = patterns; 8392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard while (pattern != NULL) 8492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 8592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard struct section_pattern *p = pattern; 8692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard pattern = p->next; 8792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard free (p->pattern); 8892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard free (p); 8992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 9092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard} 9192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 9292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardstatic error_t 9392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardparse_opt (int key, char *arg __attribute__ ((unused)), 9492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard struct argp_state *state __attribute__ ((unused))) 9592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard{ 9692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard switch (key) 9792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 9892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard case 'v': 9992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard verbose++; 10092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard break; 10192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 10292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard case 'q': 10392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard verbose--; 10492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 10592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard case 'f': 10692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard force = true; 10792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard break; 10892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 10992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard case 'p': 11092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard permissive = true; 11192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard break; 11292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 11392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard case 'n': 11492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard add_pattern (arg); 11592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard break; 11692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 11792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard case 'o': 11892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (foutput != NULL) 11992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard argp_error (state, N_("-o option specified twice")); 12092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else 12192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard foutput = arg; 12292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard break; 12392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 12492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard case 't': 12592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (type != T_UNSET) 12692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard argp_error (state, N_("-t option specified twice")); 12792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 12892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (strcmp ("none", arg) == 0) 12992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard type = T_DECOMPRESS; 13092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else if (strcmp ("zlib", arg) == 0 || strcmp ("zlib-gabi", arg) == 0) 13192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard type = T_COMPRESS_ZLIB; 13292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else if (strcmp ("zlib-gnu", arg) == 0 || strcmp ("gnu", arg) == 0) 13392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard type = T_COMPRESS_GNU; 13492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else 13592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard argp_error (state, N_("unknown compression type '%s'"), arg); 13692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard break; 13792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 13892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard case ARGP_KEY_SUCCESS: 13992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (type == T_UNSET) 14092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard type = T_COMPRESS_ZLIB; 14192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (patterns == NULL) 14292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard add_pattern (".?(z)debug*"); 14392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard break; 14492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 14592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard case ARGP_KEY_NO_ARGS: 14692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* We need at least one input file. */ 14792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard argp_error (state, N_("No input file given")); 14892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard break; 14992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 15092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard case ARGP_KEY_ARGS: 15192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (foutput != NULL && state->argc - state->next > 1) 15292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard argp_error (state, 15392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard N_("Only one input file allowed together with '-o'")); 15492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* We only use this for checking the number of arguments, we don't 15592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard actually want to consume them, so fallthrough. */ 15692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard default: 15792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return ARGP_ERR_UNKNOWN; 15892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 15992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return 0; 16092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard} 16192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 16292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardstatic bool 16392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardsection_name_matches (const char *name) 16492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard{ 16592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard struct section_pattern *pattern = patterns; 16692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard while (pattern != NULL) 16792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 16892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (fnmatch (pattern->pattern, name, FNM_EXTMATCH) == 0) 16992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return true; 17092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard pattern = pattern->next; 17192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 17292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return false; 17392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard} 17492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 17592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardstatic int 17692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardsetshdrstrndx (Elf *elf, GElf_Ehdr *ehdr, size_t ndx) 17792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard{ 17892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (ndx < SHN_LORESERVE) 17992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard ehdr->e_shstrndx = ndx; 18092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else 18192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 18292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard ehdr->e_shstrndx = SHN_XINDEX; 18392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Elf_Scn *zscn = elf_getscn (elf, 0); 18492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Shdr zshdr_mem; 18592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Shdr *zshdr = gelf_getshdr (zscn, &zshdr_mem); 18692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (zshdr == NULL) 18792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return -1; 18892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard zshdr->sh_link = ndx; 18992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (gelf_update_shdr (zscn, zshdr) == 0) 19092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return -1; 19192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 19292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 19392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (gelf_update_ehdr (elf, ehdr) == 0) 19492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return -1; 19592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 19692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return 0; 19792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard} 19892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 19992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardstatic int 20092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardcompress_section (Elf_Scn *scn, size_t orig_size, const char *name, 20192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard const char *newname, size_t ndx, 20292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard bool gnu, bool compress, bool report_verbose) 20392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard{ 20492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard int res; 20592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard unsigned int flags = compress && force ? ELF_CHF_FORCE : 0; 20692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (gnu) 20792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard res = elf_compress_gnu (scn, compress ? 1 : 0, flags); 20892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else 20992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard res = elf_compress (scn, compress ? ELFCOMPRESS_ZLIB : 0, flags); 21092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 21192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (res < 0) 21292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't decompress section [%zd] %s: %s", 21392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard ndx, name, elf_errmsg (-1)); 21492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else 21592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 21692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (compress && res == 0) 21792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 21892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (verbose >= 0) 21992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard printf ("[%zd] %s NOT compressed, wouldn't be smaller\n", 22092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard ndx, name); 22192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 22292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 22392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (report_verbose && res > 0) 22492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 22592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard printf ("[%zd] %s %s", ndx, name, 22692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard compress ? "compressed" : "decompressed"); 22792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (newname != NULL) 22892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard printf (" -> %s", newname); 22992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 23092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Reload shdr, it has changed. */ 23192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Shdr shdr_mem; 23292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 23392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (shdr == NULL) 23492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 23592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get shdr for section [%zd]", ndx); 23692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return -1; 23792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 23892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard float new = shdr->sh_size; 23992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard float orig = orig_size ?: 1; 2403a5fc51573ae88a06d2050ef8425336e23013852Mark Wielaard printf (" (%zu => %" PRIu64 " %.2f%%)\n", 24192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard orig_size, shdr->sh_size, (new / orig) * 100); 24292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 24392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 24492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 24592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return res; 24692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard} 24792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 24892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardstatic int 24992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardprocess_file (const char *fname) 25092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard{ 25192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (verbose > 0) 25292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard printf ("processing: %s\n", fname); 25392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 25492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* The input ELF. */ 25592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard int fd = -1; 25692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Elf *elf = NULL; 25792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 25892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* The output ELF. */ 25992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard char *fnew = NULL; 26092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard int fdnew = -1; 26192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Elf *elfnew = NULL; 26292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 26392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Buffer for (one) new section name if necessary. */ 26492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard char *snamebuf = NULL; 26592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 26692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* String table (and symbol table), if section names need adjusting. */ 26792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard struct Ebl_Strtab *names = NULL; 26892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard struct Ebl_Strent **scnstrents = NULL; 26992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard struct Ebl_Strent **symstrents = NULL; 27092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard char **scnnames = NULL; 27192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 27292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Section data from names. */ 27392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard void *namesbuf = NULL; 27492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 27592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Which sections match and need to be (un)compressed. */ 27692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard unsigned int *sections = NULL; 27792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 27892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* How many sections are we talking about? */ 27992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard size_t shnum = 0; 28092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 28192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard#define WORD_BITS (8U * sizeof (unsigned int)) 28292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard void set_section (size_t ndx) 28392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 28492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard sections[ndx / WORD_BITS] |= (1U << (ndx % WORD_BITS)); 28592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 28692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 28792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard bool get_section (size_t ndx) 28892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 28992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return (sections[ndx / WORD_BITS] & (1U << (ndx % WORD_BITS))) != 0; 29092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 29192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 29292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard int cleanup (int res) 29392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 29492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard elf_end (elf); 29592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard close (fd); 29692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 29792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard elf_end (elfnew); 29892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard close (fdnew); 29992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 30092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (fnew != NULL) 30192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 30292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard unlink (fnew); 30392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard free (fnew); 30492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard fnew = NULL; 30592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 30692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 30792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard free (snamebuf); 30892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (names != NULL) 30992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 31092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard ebl_strtabfree (names); 31192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard free (scnstrents); 31292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard free (symstrents); 31392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard free (namesbuf); 31492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (scnnames != NULL) 31592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 31692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard for (size_t n = 0; n < shnum; n++) 31792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard free (scnnames[n]); 31892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard free (scnnames); 31992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 32092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 32192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 32292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard free (sections); 32392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 32492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return res; 32592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 32692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 32792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard fd = open (fname, O_RDONLY); 32892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (fd < 0) 32992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 33092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, errno, "Couldn't open %s\n", fname); 33192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 33292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 33392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 33492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard elf = elf_begin (fd, ELF_C_READ, NULL); 33592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (elf == NULL) 33692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 33792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't open ELF file %s for reading: %s", 33892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard fname, elf_errmsg (-1)); 33992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 34092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 34192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 34292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* We dont' handle ar files (or anything else), we probably should. */ 34392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Elf_Kind kind = elf_kind (elf); 34492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (kind != ELF_K_ELF) 34592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 34692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (kind == ELF_K_AR) 34792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Cannot handle ar files: %s", fname); 34892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else 34992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Unknown file type: %s", fname); 35092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 35192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 35292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 35392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard struct stat st; 35492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (fstat (fd, &st) != 0) 35592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 35692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, errno, "Couldn't fstat %s", fname); 35792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 35892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 35992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 36092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Ehdr ehdr; 36192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (gelf_getehdr (elf, &ehdr) == NULL) 36292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 36392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get ehdr for %s: %s", fname, elf_errmsg (-1)); 36492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 36592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 36692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 36792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Get the section header string table. */ 36892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard size_t shdrstrndx; 36992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (elf_getshdrstrndx (elf, &shdrstrndx) != 0) 37092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 37192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get section header string table index in %s: %s", 37292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard fname, elf_errmsg (-1)); 37392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 37492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 37592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 37692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* How many sections are we talking about? */ 37792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (elf_getshdrnum (elf, &shnum) != 0) 37892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 37992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get number of sections in %s: %s", 38092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard fname, elf_errmsg (1)); 38192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 38292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 38392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 38492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (shnum == 0) 38592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 38692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "ELF file %s has no sections", fname); 38792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 38892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 38992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 39092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard sections = xcalloc (shnum / 8 + 1, sizeof (unsigned int)); 39192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 39292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard size_t phnum; 39392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (elf_getphdrnum (elf, &phnum) != 0) 39492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 39592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get phdrnum: %s", elf_errmsg (-1)); 39692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 39792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 39892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 39992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Whether we need to adjust any section names (going to/from GNU 40092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard naming). If so we'll need to build a new section header string 40192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard table. */ 40292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard bool adjust_names = false; 40392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 40492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* If there are phdrs we want to maintain the layout of the 40592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard allocated sections in the file. */ 40692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard bool layout = phnum != 0; 40792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 40892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* While going through all sections keep track of last section data 40992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard offset if needed to keep the layout. We are responsible for 41092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard adding the section offsets and headers (e_shoff) in that case 41192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard (which we will place after the last section). */ 41292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Off last_offset = 0; 41392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (layout) 41492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard last_offset = (ehdr.e_phoff 41592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard + gelf_fsize (elf, ELF_T_PHDR, phnum, EV_CURRENT)); 41692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 41792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Which section, if any, is a symbol table that shares a string 41892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard table with the section header string table? */ 41992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard size_t symtabndx = 0; 42092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 42192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* We do three passes over all sections. 42292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 42392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard First an inspection pass over the old Elf to see which section 42492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard data needs to be copied and/or transformed, which sections need a 42592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard names change and whether there is a symbol table that might need 42692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard to be adjusted be if the section header name table is changed. 42792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 42892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Second a collection pass that creates the Elf sections and copies 42992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard the data. This pass will compress/decompress section data when 43092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard needed. And it will collect all data needed if we'll need to 43192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard construct a new string table. Afterwards the new string table is 43292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard constructed. 43392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 43492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Third a fixup/adjustment pass over the new Elf that will adjust 43592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard any section references (names) and adjust the layout based on the 43692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard new sizes of the sections if necessary. This pass is optional if 43792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard we aren't responsible for the layout and the section header 43892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard string table hasn't been changed. */ 43992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 44092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Inspection pass. */ 44192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard size_t maxnamelen = 0; 44292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Elf_Scn *scn = NULL; 44392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard while ((scn = elf_nextscn (elf, scn)) != NULL) 44492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 44592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard size_t ndx = elf_ndxscn (scn); 44692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (ndx > shnum) 44792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 44892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Unexpected section number %zd, expected only %zd", 44992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard ndx, shnum); 45092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard cleanup (-1); 45192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 45292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 45392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Shdr shdr_mem; 45492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 45592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (shdr == NULL) 45692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 45792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get shdr for section %zd", ndx); 45892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 45992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 46092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 46192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard const char *sname = elf_strptr (elf, shdrstrndx, shdr->sh_name); 46292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (sname == NULL) 46392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 46492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get name for section %zd", ndx); 46592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 46692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 46792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 46892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (section_name_matches (sname)) 46992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 47092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (shdr->sh_type != SHT_NOBITS 47192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard && (shdr->sh_flags & SHF_ALLOC) == 0) 47292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 47392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard set_section (ndx); 47492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Check if we might want to change this section name. */ 47592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (! adjust_names 47692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard && ((type != T_COMPRESS_GNU 47792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard && strncmp (sname, ".zdebug", 47892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard strlen (".zdebug")) == 0) 47992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard || (type == T_COMPRESS_GNU 48092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard && strncmp (sname, ".debug", 48192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard strlen (".debug")) == 0))) 48292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard adjust_names = true; 48392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 48492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* We need a buffer this large if we change the names. */ 48592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (adjust_names) 48692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 48792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard size_t slen = strlen (sname); 48892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (slen > maxnamelen) 48992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard maxnamelen = slen; 49092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 49192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 49292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else 49392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (verbose >= 0) 49492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard printf ("[%zd] %s ignoring %s section\n", ndx, sname, 49592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard (shdr->sh_type == SHT_NOBITS ? "no bits" : "allocated")); 49692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 49792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 49892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (shdr->sh_type == SHT_SYMTAB) 49992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 50092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Check if we might have to adjust the symbol name indexes. */ 50192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (shdr->sh_link == shdrstrndx) 50292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 50392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (symtabndx != 0) 50492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 50592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, 50692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard "Multiple symbol tables (%zd, %zd) using the same string table unsupported", symtabndx, ndx); 50792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 50892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 50992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtabndx = ndx; 51092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 51192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 51292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 51392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Keep track of last allocated data offset. */ 51492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (layout) 51592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if ((shdr->sh_flags & SHF_ALLOC) != 0) 51692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 51792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Off off = shdr->sh_offset + (shdr->sh_type != SHT_NOBITS 51892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard ? shdr->sh_size : 0); 51992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (last_offset < off) 52092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard last_offset = off; 52192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 52292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 52392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 52492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (adjust_names) 52592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 52692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard names = ebl_strtabinit (true); 52792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (names == NULL) 52892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 52992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Not enough memory for new strtab"); 53092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 53192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 53292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard scnstrents = xmalloc (shnum 53392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard * sizeof (struct Ebl_Strent *)); 53492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard scnnames = xcalloc (shnum, sizeof (char *)); 53592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 53692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 53792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Create a new (temporary) ELF file for the result. */ 53892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (foutput == NULL) 53992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 54092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard size_t fname_len = strlen (fname); 54192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard fnew = xmalloc (fname_len + sizeof (".XXXXXX")); 54292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard strcpy (mempcpy (fnew, fname, fname_len), ".XXXXXX"); 54392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard fdnew = mkstemp (fnew); 54492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 54592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else 54692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 54792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard fnew = xstrdup (foutput); 54892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard fdnew = open (fnew, O_WRONLY | O_CREAT, st.st_mode & ALLPERMS); 54992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 55092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 55192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (fdnew < 0) 55292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 55392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, errno, "Couldn't create output file %s", fnew); 55492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Since we didn't create it we don't want to try to unlink it. */ 55592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard free (fnew); 55692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard fnew = NULL; 55792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 55892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 55992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 56092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard elfnew = elf_begin (fdnew, ELF_C_WRITE, NULL); 56192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (elfnew == NULL) 56292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 56392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't open new ELF %s for writing: %s", 56492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard fnew, elf_errmsg (-1)); 56592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 56692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 56792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 56892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Create the new ELF header and copy over all the data. */ 56992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (gelf_newehdr (elfnew, gelf_getclass (elf)) == 0) 57092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 57192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't create new ehdr: %s", elf_errmsg (-1)); 57292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 57392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 57492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 57592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Ehdr newehdr; 57692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (gelf_getehdr (elfnew, &newehdr) == NULL) 57792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 57892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get new ehdr: %s", elf_errmsg (-1)); 57992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 58092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 58192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 58292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard newehdr.e_ident[EI_DATA] = ehdr.e_ident[EI_DATA]; 58392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard newehdr.e_type = ehdr.e_type; 58492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard newehdr.e_machine = ehdr.e_machine; 58592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard newehdr.e_version = ehdr.e_version; 58692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard newehdr.e_entry = ehdr.e_entry; 58792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard newehdr.e_flags = ehdr.e_flags; 58892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 58992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (gelf_update_ehdr (elfnew, &newehdr) == 0) 59092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 59192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't update ehdr: %s", elf_errmsg (-1)); 59292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 59392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 59492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 59592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Copy over the phdrs as is. */ 59692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (phnum != 0) 59792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 59892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (gelf_newphdr (elfnew, phnum) == 0) 59992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 60092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't create phdrs: %s", elf_errmsg (-1)); 60192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 60292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 60392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 60492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard for (size_t cnt = 0; cnt < phnum; ++cnt) 60592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 60692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Phdr phdr_mem; 60792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem); 60892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (phdr == NULL) 60992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 61092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get phdr %zd: %s", cnt, elf_errmsg (-1)); 61192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 61292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 61392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (gelf_update_phdr (elfnew, cnt, phdr) == 0) 61492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 61592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't create phdr %zd: %s", cnt, 61692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard elf_errmsg (-1)); 61792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 61892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 61992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 62092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 62192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 62292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Possibly add a 'z' and zero terminator. */ 62392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (maxnamelen > 0) 62492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard snamebuf = xmalloc (maxnamelen + 2); 62592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 62692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* We might want to read/adjust the section header strings and 62792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symbol tables. If so, and those sections are to be compressed 62892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard then we will have to decompress it during the collection pass and 62992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard compress it again in the fixup pass. Don't compress unnecessary 63092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard and keep track of whether or not to compress them (later in the 63192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard fixup pass). Also record the original size, so we can report the 63292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard difference later when we do compress. */ 63392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard int shstrtab_compressed = T_UNSET; 63492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard size_t shstrtab_size = 0; 63592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard char *shstrtab_name = NULL; 63692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard char *shstrtab_newname = NULL; 63792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard int symtab_compressed = T_UNSET; 63892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard size_t symtab_size = 0; 63992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard char *symtab_name = NULL; 64092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard char *symtab_newname = NULL; 64192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 64292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Collection pass. Copy over the sections, (de)compresses matching 64392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard sections, collect names of sections and symbol table if 64492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard necessary. */ 64592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard scn = NULL; 64692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard while ((scn = elf_nextscn (elf, scn)) != NULL) 64792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 64892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard size_t ndx = elf_ndxscn (scn); 64992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard assert (ndx < shnum); 65092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 65192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* (de)compress if section matched. */ 65292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard char *sname = NULL; 65392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard char *newname = NULL; 65492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (get_section (ndx)) 65592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 65692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Shdr shdr_mem; 65792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 65892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (shdr == NULL) 65992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 66092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get shdr for section %zd", ndx); 66192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 66292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 66392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 66492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard uint64_t size = shdr->sh_size; 66592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard sname = elf_strptr (elf, shdrstrndx, shdr->sh_name); 66692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (sname == NULL) 66792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 66892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get name for section %zd", ndx); 66992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 67092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 67192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 67292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* strdup sname, the shdrstrndx section itself might be 67392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard (de)compressed, invalidating the string pointers. */ 67492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard sname = xstrdup (sname); 67592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 67692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* We might want to decompress (and rename), but not 67792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard compress during this pass since we might need the section 67892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard data in later passes. Skip those sections for now and 67992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard compress them in the fixup pass. */ 68092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard bool skip_compress_section = (adjust_names 68192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard && (ndx == shdrstrndx 68292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard || ndx == symtabndx)); 68392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 68492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard switch (type) 68592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 68692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard case T_DECOMPRESS: 68792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if ((shdr->sh_flags & SHF_COMPRESSED) != 0) 68892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 68992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (compress_section (scn, size, sname, NULL, ndx, 69092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard false, false, verbose > 0) < 0) 69192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 69292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 69392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else if (strncmp (sname, ".zdebug", strlen (".zdebug")) == 0) 69492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 69592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard snamebuf[0] = '.'; 69692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard strcpy (&snamebuf[1], &sname[2]); 69792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard newname = snamebuf; 69892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (compress_section (scn, size, sname, newname, ndx, 69992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard true, false, verbose > 0) < 0) 70092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 70192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 70292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else if (verbose > 0) 70392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard printf ("[%zd] %s already decompressed\n", ndx, sname); 70492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard break; 70592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 70692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard case T_COMPRESS_GNU: 70792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (strncmp (sname, ".debug", strlen (".debug")) == 0) 70892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 70992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if ((shdr->sh_flags & SHF_COMPRESSED) != 0) 71092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 71192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* First decompress to recompress GNU style. 71292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Don't report even when verbose. */ 71392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (compress_section (scn, size, sname, NULL, ndx, 71492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard false, false, false) < 0) 71592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 71692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 71792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 71892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard snamebuf[0] = '.'; 71992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard snamebuf[1] = 'z'; 72092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard strcpy (&snamebuf[2], &sname[1]); 72192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard newname = snamebuf; 72292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 72392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (skip_compress_section) 72492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 72592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (ndx == shdrstrndx) 72692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 72792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shstrtab_size = size; 72892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shstrtab_compressed = T_COMPRESS_GNU; 72992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shstrtab_name = xstrdup (sname); 73092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shstrtab_newname = xstrdup (newname); 73192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 73292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else 73392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 73492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab_size = size; 73592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab_compressed = T_COMPRESS_GNU; 73692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab_name = xstrdup (sname); 73792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab_newname = xstrdup (newname); 73892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 73992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 74092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else 74192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 74292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard int res = compress_section (scn, size, sname, newname, 74392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard ndx, true, true, 74492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard verbose > 0); 74592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (res < 0) 74692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 74792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 74892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (res == 0) 74992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard newname = NULL; 75092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 75192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 75292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else if (verbose >= 0) 75392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 75492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (strncmp (sname, ".zdebug", strlen (".zdebug")) == 0) 75592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard printf ("[%zd] %s unchanged, already GNU compressed", 75692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard ndx, sname); 75792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else 75892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard printf ("[%zd] %s cannot GNU compress section not starting with .debug\n", 75992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard ndx, sname); 76092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 76192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard break; 76292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 76392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard case T_COMPRESS_ZLIB: 76492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if ((shdr->sh_flags & SHF_COMPRESSED) == 0) 76592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 76692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (strncmp (sname, ".zdebug", strlen (".zdebug")) == 0) 76792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 76892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* First decompress to recompress zlib style. 76992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Don't report even when verbose. */ 77092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (compress_section (scn, size, sname, NULL, ndx, 77192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard true, false, false) < 0) 77292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 77392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 77492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard snamebuf[0] = '.'; 77592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard strcpy (&snamebuf[1], &sname[2]); 77692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard newname = snamebuf; 77792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 77892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 77992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (skip_compress_section) 78092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 78192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (ndx == shdrstrndx) 78292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 78392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shstrtab_size = size; 78492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shstrtab_compressed = T_COMPRESS_ZLIB; 78592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shstrtab_name = xstrdup (sname); 78692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shstrtab_newname = (newname == NULL 78792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard ? NULL : xstrdup (newname)); 78892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 78992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else 79092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 79192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab_size = size; 79292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab_compressed = T_COMPRESS_ZLIB; 79392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab_name = xstrdup (sname); 79492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab_newname = (newname == NULL 79592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard ? NULL : xstrdup (newname)); 79692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 79792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 79892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else if (compress_section (scn, size, sname, newname, ndx, 79992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard false, true, verbose > 0) < 0) 80092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 80192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 80292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else if (verbose > 0) 80392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard printf ("[%zd] %s already compressed\n", ndx, sname); 80492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard break; 80592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 80692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 80792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard free (sname); 80892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 80992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 81092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Elf_Scn *newscn = elf_newscn (elfnew); 81192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (newscn == NULL) 81292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 81392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't create new section %zd", ndx); 81492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 81592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 81692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 81792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Shdr shdr_mem; 81892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 81992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (shdr == NULL) 82092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 82192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get shdr for section %zd", ndx); 82292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 82392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 82492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 82592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (gelf_update_shdr (newscn, shdr) == 0) 82692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 82792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't update section header %zd", ndx); 82892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 82992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 83092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 83192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Except for the section header string table all data can be 83292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard copied as is. The section header string table will be 83392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard created later and the symbol table might be fixed up if 83492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard necessary. */ 83592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (! adjust_names || ndx != shdrstrndx) 83692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 83792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Elf_Data *data = elf_getdata (scn, NULL); 83892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (data == NULL) 83992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 84092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get data from section %zd", ndx); 84192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 84292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 84392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 84492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Elf_Data *newdata = elf_newdata (newscn); 84592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (newdata == NULL) 84692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 84792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't create new data for section %zd", ndx); 84892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 84992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 85092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 85192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard *newdata = *data; 85292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 85392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 85492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Keep track of the (new) section names. */ 85592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (adjust_names) 85692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 85792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard char *name; 85892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (newname != NULL) 85992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard name = newname; 86092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else 86192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 86292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard name = elf_strptr (elf, shdrstrndx, shdr->sh_name); 86392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (name == NULL) 86492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 86592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get name for section [%zd]", ndx); 86692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 86792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 86892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 86992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 87092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* We need to keep a copy of the name till the strtab is done. */ 87192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard name = scnnames[ndx] = xstrdup (name); 87292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if ((scnstrents[ndx] = ebl_strtabadd (names, name, 0)) == NULL) 87392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 87492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "No memory to add section name string table"); 87592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 87692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 87792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 87892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* If the symtab shares strings then add those too. */ 87992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (ndx == symtabndx) 88092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 88192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* If the section is (still) compressed we'll need to 88292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard uncompress it first to adjust the data, then 88392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard recompress it in the fixup pass. */ 88492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (symtab_compressed == T_UNSET) 88592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 88692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard size_t size = shdr->sh_size; 88792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if ((shdr->sh_flags == SHF_COMPRESSED) != 0) 88892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 88992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Don't report the (internal) uncompression. */ 89092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (compress_section (newscn, size, sname, NULL, ndx, 89192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard false, false, false) < 0) 89292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 89392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 89492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab_size = size; 89592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab_compressed = T_COMPRESS_ZLIB; 89692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 89792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0) 89892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 89992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Don't report the (internal) uncompression. */ 90092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (compress_section (newscn, size, sname, NULL, ndx, 90192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard true, false, false) < 0) 90292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 90392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 90492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab_size = size; 90592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab_compressed = T_COMPRESS_GNU; 90692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 90792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 90892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 90992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Elf_Data *symd = elf_getdata (newscn, NULL); 91092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (symd == NULL) 91192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 91292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get symtab data for section [%zd] %s", 91392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard ndx, name); 91492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 91592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 91692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard size_t elsize = gelf_fsize (elfnew, ELF_T_SYM, 1, EV_CURRENT); 91792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard size_t syms = symd->d_size / elsize; 91892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symstrents = xmalloc (syms * sizeof (struct Ebl_Strent *)); 91992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard for (size_t i = 0; i < syms; i++) 92092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 92192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Sym sym_mem; 92292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Sym *sym = gelf_getsym (symd, i, &sym_mem); 92392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (sym == NULL) 92492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 92592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get symbol %zd", i); 92692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 92792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 92892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (sym->st_name != 0) 92992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 93092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Note we take the name from the original ELF, 93192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard since the new one will not have setup the 93292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard strtab yet. */ 93392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard const char *symname = elf_strptr (elf, shdrstrndx, 93492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard sym->st_name); 93592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (symname == NULL) 93692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 93792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get symbol %zd name", i); 93892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 93992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 94092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symstrents[i] = ebl_strtabadd (names, symname, 0); 94192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (symstrents[i] == NULL) 94292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 94392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "No memory to add to symbol name"); 94492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 94592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 94692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 94792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 94892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 94992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 95092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 95192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 95292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (adjust_names) 95392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 95492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* We got all needed strings, put the new data in the shstrtab. */ 95592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (verbose > 0) 95692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard printf ("[%zd] Updating section string table\n", shdrstrndx); 95792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 95892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard scn = elf_getscn (elfnew, shdrstrndx); 95992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (scn == NULL) 96092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 96192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get new section header string table [%zd]", 96292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdrstrndx); 96392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 96492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 96592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 96692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Elf_Data *data = elf_newdata (scn); 96792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (data == NULL) 96892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 96992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't create new section header string table data"); 97092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 97192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 97292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard ebl_strtabfinalize (names, data); 97392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard namesbuf = data->d_buf; 97492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 97592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Shdr shdr_mem; 97692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 97792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (shdr == NULL) 97892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 97992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get shdr for new section strings %zd", 98092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdrstrndx); 98192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 98292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 98392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 98492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Note that we also might have to compress and possibly set 98592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard sh_off below */ 98692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdr->sh_name = ebl_strtaboffset (scnstrents[shdrstrndx]); 98792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdr->sh_type = SHT_STRTAB; 98892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdr->sh_flags = 0; 98992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdr->sh_addr = 0; 99092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdr->sh_offset = 0; 99192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdr->sh_size = data->d_size; 99292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdr->sh_link = SHN_UNDEF; 99392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdr->sh_info = SHN_UNDEF; 99492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdr->sh_addralign = 1; 99592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdr->sh_entsize = 0; 99692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 99792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (gelf_update_shdr (scn, shdr) == 0) 99892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 99992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't update new section strings [%zd]", 100092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdrstrndx); 100192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 100292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 100392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 100492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* We might have to compress the data if the user asked us to, 100592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard or if the section was already compressed (and the user didn't 100692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard ask for decompression). Note somewhat identical code for 100792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab below. */ 100892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (shstrtab_compressed == T_UNSET) 100992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 101092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* The user didn't ask for compression, but maybe it was 101192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard compressed in the original ELF file. */ 101292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Elf_Scn *oldscn = elf_getscn (elf, shdrstrndx); 101392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (oldscn == NULL) 101492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 101592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get section header string table [%zd]", 101692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdrstrndx); 101792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 101892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 101992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 102092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdr = gelf_getshdr (oldscn, &shdr_mem); 102192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (shdr == NULL) 102292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 102392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get shdr for old section strings [%zd]", 102492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdrstrndx); 102592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 102692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 102792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 102892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shstrtab_name = elf_strptr (elf, shdrstrndx, shdr->sh_name); 102992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (shstrtab_name == NULL) 103092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 103192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get name for old section strings [%zd]", 103292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdrstrndx); 103392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 103492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 103592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 103692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shstrtab_size = shdr->sh_size; 103792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if ((shdr->sh_flags & SHF_COMPRESSED) != 0) 103892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shstrtab_compressed = T_COMPRESS_ZLIB; 103992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else if (strncmp (shstrtab_name, ".zdebug", strlen (".zdebug")) == 0) 104092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shstrtab_compressed = T_COMPRESS_GNU; 104192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 104292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 104392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Should we (re)compress? */ 104492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (shstrtab_compressed != T_UNSET) 104592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 104692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (compress_section (scn, shstrtab_size, shstrtab_name, 104792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shstrtab_newname, shdrstrndx, 104892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shstrtab_compressed == T_COMPRESS_GNU, 104992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard true, verbose > 0) < 0) 105092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 105192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 105292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 105392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 105492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Make sure to re-get the new ehdr. Adding phdrs and shdrs will 105592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard have changed it. */ 105692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (gelf_getehdr (elfnew, &newehdr) == NULL) 105792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 105892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't re-get new ehdr: %s", elf_errmsg (-1)); 105992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 106092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 106192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 106292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Set this after the sections have been created, otherwise section 106392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard zero might not exist yet. */ 106492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (setshdrstrndx (elfnew, &newehdr, shdrstrndx) != 0) 106592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 106692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't set new shdrstrndx: %s", elf_errmsg (-1)); 106792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 106892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 106992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 107092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Fixup pass. Adjust string table references, symbol table and 107192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard layout if necessary. */ 107292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (layout || adjust_names) 107392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 107492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard scn = NULL; 107592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard while ((scn = elf_nextscn (elfnew, scn)) != NULL) 107692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 107792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard size_t ndx = elf_ndxscn (scn); 107892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 107992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Shdr shdr_mem; 108092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 108192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (shdr == NULL) 108292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 108392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get shdr for section %zd", ndx); 108492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 108592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 108692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 108792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Keep the offset of allocated sections so they are at the 108892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard same place in the file. Add (possibly changed) 108992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard unallocated ones after the allocated ones. */ 109092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if ((shdr->sh_flags & SHF_ALLOC) == 0) 109192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 109292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Zero means one. No alignment constraints. */ 109392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard size_t addralign = shdr->sh_addralign ?: 1; 109492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard last_offset = (last_offset + addralign - 1) & ~(addralign - 1); 109592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdr->sh_offset = last_offset; 109692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (shdr->sh_type != SHT_NOBITS) 109792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard last_offset += shdr->sh_size; 109892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 109992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 110092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (adjust_names) 110192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdr->sh_name = ebl_strtaboffset (scnstrents[ndx]); 110292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 110392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (gelf_update_shdr (scn, shdr) == 0) 110492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 110592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't update section header %zd", ndx); 110692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 110792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 110892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 110992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (adjust_names && ndx == symtabndx) 111092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 111192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (verbose > 0) 111292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard printf ("[%zd] Updating symbol table\n", symtabndx); 111392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 111492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Elf_Data *symd = elf_getdata (scn, NULL); 111592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (symd == NULL) 111692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 111792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get new symtab data section [%zd]", 111892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard ndx); 111992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 112092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 112192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard size_t elsize = gelf_fsize (elfnew, ELF_T_SYM, 1, EV_CURRENT); 112292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard size_t syms = symd->d_size / elsize; 112392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard for (size_t i = 0; i < syms; i++) 112492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 112592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Sym sym_mem; 112692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard GElf_Sym *sym = gelf_getsym (symd, i, &sym_mem); 112792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (sym == NULL) 112892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 112992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "2 Couldn't get symbol %zd", i); 113092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 113192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 113292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 113392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (sym->st_name != 0) 113492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 113592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard sym->st_name = ebl_strtaboffset (symstrents[i]); 113692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 113792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (gelf_update_sym (symd, i, sym) == 0) 113892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 113992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't update symbol %zd", i); 114092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 114192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 114292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 114392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 114492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 114592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* We might have to compress the data if the user asked 114692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard us to, or if the section was already compressed (and 114792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard the user didn't ask for decompression). Note 114892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard somewhat identical code for shstrtab above. */ 114992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (symtab_compressed == T_UNSET) 115092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 115192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* The user didn't ask for compression, but maybe it was 115292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard compressed in the original ELF file. */ 115392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Elf_Scn *oldscn = elf_getscn (elf, symtabndx); 115492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (oldscn == NULL) 115592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 115692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get symbol table [%zd]", 115792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtabndx); 115892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 115992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 116092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 116192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard shdr = gelf_getshdr (oldscn, &shdr_mem); 116292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (shdr == NULL) 116392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 116492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get old symbol table shdr [%zd]", 116592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtabndx); 116692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 116792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 116892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 116992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab_name = elf_strptr (elf, shdrstrndx, shdr->sh_name); 117092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (symtab_name == NULL) 117192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 117292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get old symbol table name [%zd]", 117392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtabndx); 117492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 117592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 117692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 117792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab_size = shdr->sh_size; 117892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if ((shdr->sh_flags & SHF_COMPRESSED) != 0) 117992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab_compressed = T_COMPRESS_ZLIB; 118092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard else if (strncmp (symtab_name, ".zdebug", 118192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard strlen (".zdebug")) == 0) 118292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab_compressed = T_COMPRESS_GNU; 118392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 118492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 118592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Should we (re)compress? */ 118692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (symtab_compressed != T_UNSET) 118792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 118892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (compress_section (scn, symtab_size, symtab_name, 118992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab_newname, symtabndx, 119092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard symtab_compressed == T_COMPRESS_GNU, 119192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard true, verbose > 0) < 0) 119292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 119392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 119492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 119592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 119692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 119792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 119892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* If we have phdrs we want elf_update to layout the SHF_ALLOC 119992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard sections precisely as in the original file. In that case we are 120092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard also responsible for setting phoff and shoff */ 120192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (layout) 120292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 120392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (gelf_getehdr (elfnew, &newehdr) == NULL) 120492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 120592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't get ehdr: %s", elf_errmsg (-1)); 120692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 120792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 120892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 120992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Position the shdrs after the last (unallocated) section. */ 121092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard const size_t offsize = gelf_fsize (elfnew, ELF_T_OFF, 1, EV_CURRENT); 121192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard newehdr.e_shoff = ((last_offset + offsize - 1) 121292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard & ~((GElf_Off) (offsize - 1))); 121392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 121492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* The phdrs go in the same place as in the original file. 121592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard Normally right after the ELF header. */ 121692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard newehdr.e_phoff = ehdr.e_phoff; 121792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 121892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (gelf_update_ehdr (elfnew, &newehdr) == 0) 121992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 122092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't update ehdr: %s", elf_errmsg (-1)); 122192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 122292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 122392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 122492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 122592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard elf_flagelf (elfnew, ELF_C_SET, ((layout ? ELF_F_LAYOUT : 0) 122692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard | (permissive ? ELF_F_PERMISSIVE : 0))); 122792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 122892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (elf_update (elfnew, ELF_C_WRITE) < 0) 122992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 123092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, 0, "Couldn't write %s: %s", fnew, elf_errmsg (-1)); 123192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 123292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 123392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 123492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard elf_end (elfnew); 123592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard elfnew = NULL; 123692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 123792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Try to match mode and owner.group of the original file. */ 123892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (fchmod (fdnew, st.st_mode & ALLPERMS) != 0) 123992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (verbose >= 0) 124092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, errno, "Couldn't fchmod %s", fnew); 124192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (fchown (fdnew, st.st_uid, st.st_gid) != 0) 124292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (verbose >= 0) 124392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, errno, "Couldn't fchown %s", fnew); 124492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 124592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Finally replace the old file with the new file. */ 124692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (foutput == NULL) 124792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (rename (fnew, fname) != 0) 124892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 124992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (0, errno, "Couldn't rename %s to %s", fnew, fname); 125092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (-1); 125192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard } 125292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 125392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* We are finally done with the new file, don't unlink it now. */ 125492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard free (fnew); 125592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard fnew = NULL; 125692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 125792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return cleanup (0); 125892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard} 125992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 126092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardint 126192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaardmain (int argc, char **argv) 126292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard{ 126392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard const struct argp_option options[] = 126492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 126592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { "output", 'o', "FILE", 0, 126692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard N_("Place (de)compressed output into FILE"), 126792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 0 }, 126892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { "type", 't', "TYPE", 0, 126992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 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)"), 127092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 0 }, 127192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { "name", 'n', "SECTION", 0, 127292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard N_("SECTION name to (de)compress, SECTION is an extended wildcard pattern (defaults to '.?(z)debug*')"), 127392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 0 }, 127492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { "verbose", 'v', NULL, 0, 127592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard N_("Print a message for each section being (de)compressed"), 127692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 0 }, 127792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { "force", 'f', NULL, 0, 127892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard N_("Force compression of section even if it would become larger"), 127992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 0 }, 128092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { "permissive", 'p', NULL, 0, 128192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard N_("Relax a few rules to handle slightly broken ELF files"), 128292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 0 }, 128392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { "quiet", 'q', NULL, 0, 128492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard N_("Be silent when a section cannot be compressed"), 128592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 0 }, 128692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { NULL, 0, NULL, 0, NULL, 0 } 128792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard }; 128892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 128992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard const struct argp argp = 129092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard { 129192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard .options = options, 129292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard .parser = parse_opt, 129392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard .args_doc = N_("FILE..."), 129492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard .doc = N_("Compress or decompress sections in an ELF file.") 129592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard }; 129692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 129792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard int remaining; 129892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (argp_parse (&argp, argc, argv, 0, &remaining, NULL) != 0) 129992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return EXIT_FAILURE; 130092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 130192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Should already be handled by ARGP_KEY_NO_ARGS case above, 130292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard just sanity check. */ 130392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (remaining >= argc) 130492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (EXIT_FAILURE, 0, N_("No input file given")); 130592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 130692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Likewise for the ARGP_KEY_ARGS case above, an extra sanity check. */ 130792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard if (foutput != NULL && remaining + 1 < argc) 130892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard error (EXIT_FAILURE, 0, 130992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard N_("Only one input file allowed together with '-o'")); 131092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 131192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard elf_version (EV_CURRENT); 131292acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 131392acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard /* Process all the remaining files. */ 131492acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard int result = 0; 131592acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard do 131692acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard result |= process_file (argv[remaining]); 131792acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard while (++remaining < argc); 131892acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard 131992acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard free_patterns (); 132092acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard return result; 132192acb57eb0468de93c4976eb1de6bf08ede9abd0Mark Wielaard} 1322