Bug 21332 - elflint doesn't handle compressed sections
Summary: elflint doesn't handle compressed sections
Status: RESOLVED FIXED
Alias: None
Product: elfutils
Classification: Unclassified
Component: tools (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-03-30 09:13 UTC by Richard Biener
Modified: 2017-04-06 13:34 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Richard Biener 2017-03-30 09:13:43 UTC
On s390x we see

[   54s] FAIL: run-strip-strmerge.sh
[   55s] FAIL: run-elflint-self.sh
[   68s] # XFAIL: 0
[   68s] # FAIL:  2

cat home/abuild/rpmbuild/BUILD/elfutils-0.168/tests/run-strip-strmerge.sh.log 
elflint /home/abuild/rpmbuild/BUILD/elfutils-0.168/tests/elfstrmerge
No errors
elfstrmerge
elflint merged.elf
No errors
strip
elflint merged.elf.stripped
No errors
elflint merged.elf.debug
No errors
unstrip
elflint remerged.elf
No errors
elfcmp
elflint /home/abuild/rpmbuild/BUILD/elfutils-0.168/tests/elfstrmerge.o
section [28] '.symtab': symbol 109: st_value out of bounds
section [28] '.symtab': symbol 114: st_value out of bounds
..
FAIL run-strip-strmerge.sh (exit status: 1)

for example:

   109: 0000000000000cc7     0 NOTYPE  LOCAL  DEFAULT   23 .LASF354

  [23] .debug_str        PROGBITS         0000000000000000  00003829
       000000000000075a  0000000000000001 MSC       0     0     1

So it looks like this is an elflint bug which simply doesn't handle
compressed sections (C flag).  Or handling it bogously and just on s390x...

The source does

                  if (! ebl_check_special_symbol (ebl, ehdr, sym, name,
                                                  destshdr))
                    {
                      if (st_value - sh_addr > destshdr->sh_size)
                        {

and check_special_symbol has no implementation in the s390 backend.

Probably not relevant, but destshdr->sh_size may not be the uncompressed
size here as it is accessed just via gelf_getshdr which doesn't seem to do
any uncompression.

On x86_64 I do not see the debug strings in .symtab for some reason,
the relocations are done via .debug_str + offset (R_X86_64_32) while
on s390x we have .LASF8 + 0 (R_390_32).  Looks like a GNU as deficiency
on s390x to me though.
Comment 1 Mark Wielaard 2017-03-30 12:34:44 UTC
eu-elflint probably doesn't handle compressed ELF sections. And it would be some work to make it handle them because it does check various references between sections and seems to assume any of those are against normal (uncompressed) sections.

The question is how did a compressed ELF section end up in the elfstrmerge.o file in the first place? Especially since it apparently isn't in the resulting EXE file. Seems somehow the ET_REL file got created with a compressed ELF section, but then the linker fixed things up again?
Comment 2 rguenther 2017-03-30 12:41:08 UTC
On Thu, 30 Mar 2017, mark at klomp dot org wrote:

> https://sourceware.org/bugzilla/show_bug.cgi?id=21332
> 
> Mark Wielaard <mark at klomp dot org> changed:
> 
>            What    |Removed                     |Added
> ----------------------------------------------------------------------------
>                  CC|                            |mark at klomp dot org
> 
> --- Comment #1 from Mark Wielaard <mark at klomp dot org> ---
> eu-elflint probably doesn't handle compressed ELF sections. And it would be
> some work to make it handle them because it does check various references
> between sections and seems to assume any of those are against normal
> (uncompressed) sections.
> 
> The question is how did a compressed ELF section end up in the elfstrmerge.o
> file in the first place? Especially since it apparently isn't in the resulting
> EXE file. Seems somehow the ET_REL file got created with a compressed ELF
> section, but then the linker fixed things up again?

Recent GAS versions compress debug sections by default (but ld then
uncompresses again for the final exe).  Supposedly to improve I/O.
Comment 3 Mark Wielaard 2017-03-30 12:44:34 UTC
(In reply to rguenther from comment #2)
> On Thu, 30 Mar 2017, mark at klomp dot org wrote:
> > The question is how did a compressed ELF section end up in the elfstrmerge.o
> > file in the first place? Especially since it apparently isn't in the resulting
> > EXE file. Seems somehow the ET_REL file got created with a compressed ELF
> > section, but then the linker fixed things up again?
> 
> Recent GAS versions compress debug sections by default (but ld then
> uncompresses again for the final exe).  Supposedly to improve I/O.

That seems like a stupid default. Were there any benchmarks showing the extra compressing/decompressing cycle actually help? I am sure eu-elflint isn't the only program that cannot handle compressed ELF sections by default.
Comment 4 rguenther 2017-03-30 12:58:43 UTC
On Thu, 30 Mar 2017, mark at klomp dot org wrote:

> https://sourceware.org/bugzilla/show_bug.cgi?id=21332
> 
> --- Comment #3 from Mark Wielaard <mark at klomp dot org> ---
> (In reply to rguenther from comment #2)
> > On Thu, 30 Mar 2017, mark at klomp dot org wrote:
> > > The question is how did a compressed ELF section end up in the elfstrmerge.o
> > > file in the first place? Especially since it apparently isn't in the resulting
> > > EXE file. Seems somehow the ET_REL file got created with a compressed ELF
> > > section, but then the linker fixed things up again?
> > 
> > Recent GAS versions compress debug sections by default (but ld then
> > uncompresses again for the final exe).  Supposedly to improve I/O.
> 
> That seems like a stupid default. Were there any benchmarks showing the extra
> compressing/decompressing cycle actually help? I am sure eu-elflint isn't the
> only program that cannot handle compressed ELF sections by default.

The idea is that exposing this only (by default) for .o files the set
of tools would be small.  -Wa,--nocompress-debug-sections disables this.

As of binutils 2.27 we have

* Default to --enable-compressed-debug-sections=gas for Linux/x86 targets.

so quite narrow list of targets (not sure how s390x is affected for me
then...).
Comment 5 Mark Wielaard 2017-03-30 14:39:33 UTC
I was wondering why I hadn't seen this before. Turns out that fedora binutils is explicitly configure with --enable-compressed-debug-sections=none.
Comment 6 rguenther 2017-03-31 07:14:24 UTC
On Thu, 30 Mar 2017, mark at klomp dot org wrote:

> https://sourceware.org/bugzilla/show_bug.cgi?id=21332
> 
> --- Comment #5 from Mark Wielaard <mark at klomp dot org> ---
> I was wondering why I hadn't seen this before. Turns out that fedora binutils
> is explicitly configure with --enable-compressed-debug-sections=none.

I think the most visible improvement for compressed debug info in .o files
would be reduction in size for installed static archives.
Comment 7 Mark Wielaard 2017-04-05 15:12:41 UTC
Turns out supporting (gabi) compressed ELF sections in eu-elflint is is fairly simple by just decompressing every section unconditionally at the start (when we also check if all sections are actually there):

diff --git a/src/elflint.c b/src/elflint.c
index e0c65b6..51e53c2 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -464,6 +466,9 @@ invalid number of section header table entries\n"));
        scn = elf_nextscn (ebl->elf, scn);
        if (scn == NULL)
          break;
+       /* If the section wasn't compressed this does nothing, but
+          returns an error.  We don't care.  */
+       elf_compress (scn, 0, 0);
      }
   if (scnt < shnum)
     ERROR (gettext ("Can only check %u headers, shnum was %u\n"), scnt, shnum);

Full patch plus testcases:
https://sourceware.org/ml/elfutils-devel/2017-q2/msg00026.html

Would you be able to test that on your s390x setup?
Comment 8 rguenther 2017-04-06 07:49:13 UTC
On Wed, 5 Apr 2017, mark at klomp dot org wrote:

> https://sourceware.org/bugzilla/show_bug.cgi?id=21332
> 
> --- Comment #7 from Mark Wielaard <mark at klomp dot org> ---
> Turns out supporting (gabi) compressed ELF sections in eu-elflint is is fairly
> simple by just decompressing every section unconditionally at the start (when
> we also check if all sections are actually there):
> 
> diff --git a/src/elflint.c b/src/elflint.c
> index e0c65b6..51e53c2 100644
> --- a/src/elflint.c
> +++ b/src/elflint.c
> @@ -464,6 +466,9 @@ invalid number of section header table entries\n"));
>         scn = elf_nextscn (ebl->elf, scn);
>         if (scn == NULL)
>           break;
> +       /* If the section wasn't compressed this does nothing, but
> +          returns an error.  We don't care.  */
> +       elf_compress (scn, 0, 0);
>       }
>    if (scnt < shnum)
>      ERROR (gettext ("Can only check %u headers, shnum was %u\n"), scnt,
> shnum);
> 
> Full patch plus testcases:
> https://sourceware.org/ml/elfutils-devel/2017-q2/msg00026.html
> 
> Would you be able to test that on your s390x setup?

A quick test shows that it works.
Comment 9 Mark Wielaard 2017-04-06 13:34:19 UTC
(In reply to rguenther from comment #8)
> A quick test shows that it works.

Thanks.

commit caf135b7f49f9f3499c952b352493cf561ae12bd
Author: Mark Wielaard <mark@klomp.org>
Date:   Wed Apr 5 17:09:27 2017 +0200

    elflint: Support checking ELF files with compressed sections.
    
    Simply unconditionally uncompress any section to make sure indexes between
    sections check out. Add some testcases with various compressed sections.
    
    https://sourceware.org/bugzilla/show_bug.cgi?id=21332
    
    Signed-off-by: Mark Wielaard <mark@klomp.org>