summaryrefslogtreecommitdiffstats
path: root/src/elfcompress.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/elfcompress.c')
-rw-r--r--src/elfcompress.c62
1 files changed, 52 insertions, 10 deletions
diff --git a/src/elfcompress.c b/src/elfcompress.c
index 78dc27a4..1d6a9672 100644
--- a/src/elfcompress.c
+++ b/src/elfcompress.c
@@ -1,5 +1,5 @@
/* Compress or decompress an ELF file.
- Copyright (C) 2015, 2016 Red Hat, Inc.
+ Copyright (C) 2015, 2016, 2018 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -18,7 +18,6 @@
#include <config.h>
#include <assert.h>
#include <argp.h>
-#include <error.h>
#include <stdbool.h>
#include <stdlib.h>
#include <inttypes.h>
@@ -34,6 +33,7 @@
#include ELFUTILS_HEADER(ebl)
#include ELFUTILS_HEADER(dwelf)
#include <gelf.h>
+#include "system.h"
#include "libeu.h"
#include "printversion.h"
@@ -289,6 +289,15 @@ process_file (const char *fname)
return (sections[ndx / WORD_BITS] & (1U << (ndx % WORD_BITS))) != 0;
}
+ /* How many sections are we going to change? */
+ size_t get_sections (void)
+ {
+ size_t s = 0;
+ for (size_t i = 0; i < shnum / WORD_BITS + 1; i++)
+ s += __builtin_popcount (sections[i]);
+ return s;
+ }
+
int cleanup (int res)
{
elf_end (elf);
@@ -425,6 +434,9 @@ process_file (const char *fname)
names change and whether there is a symbol table that might need
to be adjusted be if the section header name table is changed.
+ If nothing needs changing, and the input and output file are the
+ same, we are done.
+
Second a collection pass that creates the Elf sections and copies
the data. This pass will compress/decompress section data when
needed. And it will collect all data needed if we'll need to
@@ -467,7 +479,26 @@ process_file (const char *fname)
if (section_name_matches (sname))
{
- if (shdr->sh_type != SHT_NOBITS
+ if (!force && type == T_DECOMPRESS
+ && (shdr->sh_flags & SHF_COMPRESSED) == 0
+ && strncmp (sname, ".zdebug", strlen (".zdebug")) != 0)
+ {
+ if (verbose > 0)
+ printf ("[%zd] %s already decompressed\n", ndx, sname);
+ }
+ else if (!force && type == T_COMPRESS_ZLIB
+ && (shdr->sh_flags & SHF_COMPRESSED) != 0)
+ {
+ if (verbose > 0)
+ printf ("[%zd] %s already compressed\n", ndx, sname);
+ }
+ else if (!force && type == T_COMPRESS_GNU
+ && strncmp (sname, ".zdebug", strlen (".zdebug")) == 0)
+ {
+ if (verbose > 0)
+ printf ("[%zd] %s already GNU compressed\n", ndx, sname);
+ }
+ else if (shdr->sh_type != SHT_NOBITS
&& (shdr->sh_flags & SHF_ALLOC) == 0)
{
set_section (ndx);
@@ -521,6 +552,14 @@ process_file (const char *fname)
}
}
+ if (foutput == NULL && get_sections () == 0)
+ {
+ if (verbose > 0)
+ printf ("Nothing to do.\n");
+ fnew = NULL;
+ return cleanup (0);
+ }
+
if (adjust_names)
{
names = dwelf_strtab_init (true);
@@ -1238,17 +1277,20 @@ process_file (const char *fname)
elf_end (elfnew);
elfnew = NULL;
-#if HAVE_DECL_FCHMOD
- /* Try to match mode and owner.group of the original file. */
- if (fchmod (fdnew, st.st_mode & 07777) != 0)
- if (verbose >= 0)
- error (0, errno, "Couldn't fchmod %s", fnew);
-#endif
#if HAVE_DECL_FCHOWN
+ /* Try to match mode and owner.group of the original file.
+ Note to set suid bits we have to make sure the owner is setup
+ correctly first. Otherwise fchmod will drop them silently
+ or fchown may clear them. */
if (fchown (fdnew, st.st_uid, st.st_gid) != 0)
if (verbose >= 0)
error (0, errno, "Couldn't fchown %s", fnew);
#endif
+#if HAVE_DECL_FCHMOD
+ if (fchmod (fdnew, st.st_mode & ALLPERMS) != 0)
+ if (verbose >= 0)
+ error (0, errno, "Couldn't fchmod %s", fnew);
+#endif
/* Finally replace the old file with the new file. */
if (foutput == NULL)
@@ -1283,7 +1325,7 @@ main (int argc, char **argv)
N_("Print a message for each section being (de)compressed"),
0 },
{ "force", 'f', NULL, 0,
- N_("Force compression of section even if it would become larger"),
+ N_("Force compression of section even if it would become larger or update/rewrite the file even if no section would be (de)compressed"),
0 },
{ "permissive", 'p', NULL, 0,
N_("Relax a few rules to handle slightly broken ELF files"),