SHF_COMPRESSED is a valid section flag, it can optionally be on any special
section, but it cannot be used on NOBITS sections or together with SHF_ALLOC.
A section that has SHF_COMPRESSED set must have a valid Chdr.

Signed-off-by: Mark Wielaard <m...@redhat.com>
---
 src/ChangeLog |  8 ++++++++
 src/elflint.c | 45 +++++++++++++++++++++++++++++++++++----------
 2 files changed, 43 insertions(+), 10 deletions(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index 1b5be54..a6d4a97 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,11 @@
+2015-12-18  Mark Wielaard  <m...@redhat.com>
+
+       * elflint.c (section_flags_string): Add NEWFLAG COMPRESSED.
+       (check_sections): SHF_COMPRESSED can be on any special section.
+       SHF_COMPRESSED is a valid section flag. SHF_COMPRESSED cannot
+       be used together with SHF_ALLOC or with SHT_NOBITS. Should have
+       a valid Chdr.
+
 2015-10-20  Mark Wielaard  <m...@redhat.com>
 
        * readelf.c (options): Expand -z help text.
diff --git a/src/elflint.c b/src/elflint.c
index bb97f59..7a7b9ce 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -1,5 +1,5 @@
 /* Pedantic checking of ELF files compliance with gABI/psABI spec.
-   Copyright (C) 2001-2014 Red Hat, Inc.
+   Copyright (C) 2001-2015 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drep...@redhat.com>, 2001.
 
@@ -2750,7 +2750,8 @@ section_flags_string (GElf_Word flags, char *buf, size_t 
len)
       NEWFLAG (LINK_ORDER),
       NEWFLAG (OS_NONCONFORMING),
       NEWFLAG (GROUP),
-      NEWFLAG (TLS)
+      NEWFLAG (TLS),
+      NEWFLAG (COMPRESSED)
     };
 #undef NEWFLAG
   const size_t nknown_flags = sizeof (known_flags) / sizeof (known_flags[0]);
@@ -3698,7 +3699,8 @@ zeroth section has nonzero link value while ELF header 
does not signal overflow
   size_t versym_scnndx = 0;
   for (size_t cnt = 1; cnt < shnum; ++cnt)
     {
-      shdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &shdr_mem);
+      Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
+      shdr = gelf_getshdr (scn, &shdr_mem);
       if (shdr == NULL)
        {
          ERROR (gettext ("\
@@ -3748,9 +3750,11 @@ section [%2d] '%s' has wrong type: expected %s, is 
%s\n"),
                if (special_sections[s].attrflag == exact
                    || special_sections[s].attrflag == exact_or_gnuld)
                  {
-                   /* Except for the link order and group bit all the
-                      other bits should match exactly.  */
-                   if ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP))
+                   /* Except for the link order, group bit and
+                      compression flag all the other bits should
+                      match exactly.  */
+                   if ((shdr->sh_flags
+                        & ~(SHF_LINK_ORDER | SHF_GROUP | SHF_COMPRESSED))
                        != special_sections[s].attr
                        && (special_sections[s].attrflag == exact || !gnuld))
                      ERROR (gettext ("\
@@ -3766,9 +3770,10 @@ section [%2zu] '%s' has wrong flags: expected %s, is 
%s\n"),
                  {
                    if ((shdr->sh_flags & special_sections[s].attr)
                        != special_sections[s].attr
-                       || ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP
-                                               | special_sections[s].attr
-                                               | special_sections[s].attr2))
+                       || ((shdr->sh_flags
+                            & ~(SHF_LINK_ORDER | SHF_GROUP | SHF_COMPRESSED
+                                | special_sections[s].attr
+                                | special_sections[s].attr2))
                            != 0))
                      ERROR (gettext ("\
 section [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n"),
@@ -3871,7 +3876,8 @@ section [%2zu] '%s': size not multiple of entry size\n"),
 
 #define ALL_SH_FLAGS (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE \
                      | SHF_STRINGS | SHF_INFO_LINK | SHF_LINK_ORDER \
-                     | SHF_OS_NONCONFORMING | SHF_GROUP | SHF_TLS)
+                     | SHF_OS_NONCONFORMING | SHF_GROUP | SHF_TLS \
+                     | SHF_COMPRESSED)
       if (shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS)
        {
          GElf_Xword sh_flags = shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS;
@@ -3901,6 +3907,25 @@ section [%2zu] '%s': thread-local data sections address 
not zero\n"),
          // XXX TODO more tests!?
        }
 
+      if (shdr->sh_flags & SHF_COMPRESSED)
+       {
+         if (shdr->sh_flags & SHF_ALLOC)
+           ERROR (gettext ("\
+section [%2zu] '%s': allocated section cannot be compressed\n"),
+                  cnt, section_name (ebl, cnt));
+
+         if (shdr->sh_type == SHT_NOBITS)
+           ERROR (gettext ("\
+section [%2zu] '%s': nobits section cannot be compressed\n"),
+                  cnt, section_name (ebl, cnt));
+
+         GElf_Chdr chdr;
+         if (gelf_getchdr (scn, &chdr) == NULL)
+           ERROR (gettext ("\
+section [%2zu] '%s': compressed section with no compression header: %s\n"),
+                  cnt, section_name (ebl, cnt), elf_errmsg (-1));
+       }
+
       if (shdr->sh_link >= shnum)
        ERROR (gettext ("\
 section [%2zu] '%s': invalid section reference in link value\n"),
-- 
2.5.0

Reply via email to