From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2124) id 9E79F3858C52; Tue, 14 Nov 2023 10:59:32 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9E79F3858C52 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Nick Clifton To: bfd-cvs@sourceware.org Subject: [binutils-gdb] Improve objdump's handling of compressed sections. X-Act-Checkin: binutils-gdb X-Git-Author: Nick Clifton X-Git-Refname: refs/heads/master X-Git-Oldrev: 319b460545dc79280e2904dcc280057cf71fb753 X-Git-Newrev: fab62191f84583780c2c6d024d0e583400881770 Message-Id: <20231114105932.9E79F3858C52@sourceware.org> Date: Tue, 14 Nov 2023 10:59:32 +0000 (GMT) X-BeenThere: binutils-cvs@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 14 Nov 2023 10:59:32 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3Dfab62191f845= 83780c2c6d024d0e583400881770 commit fab62191f84583780c2c6d024d0e583400881770 Author: Nick Clifton Date: Tue Nov 14 10:57:58 2023 +0000 Improve objdump's handling of compressed sections. =20 PR 31062 * objdump.c (decompressed_dumps): New local variable. (usage): Mentio= n the -z/--decompress option. (long_options): Add --decompress. (dump_secti= on_header): Add "COMPRESSED" to the Flags field of any compressed section. = (dump_section): Warn users when dumping a compressed section. (display_any_= bfd): Decompress the section if decompressed_dumps is true. (main): Handle = the -z/--decompress option. * NEWS: Mention the new feature. * doc/binutils.texi: Document the new feature. * testsuite/binutils-all/objdump.s: Update expected output. * testsuite/binutils-all/objdump.exp: Add test of -Z -s. * testsuite/binutils-all/objdump.Zs: New file. * readelf.c (maybe_expand_or_relocate_section): New function. Contain= s common code found in dump functions. Adds a note message if a compressed= section is not being decompressed. (dump_section_as_strings): Use new func= tion. (dump_section_as_bytes): Likewise. Diff: --- binutils/ChangeLog | 24 +++ binutils/NEWS | 8 + binutils/doc/binutils.texi | 15 +- binutils/objdump.c | 17 +- binutils/readelf.c | 230 ++++++++++--------------= ---- binutils/testsuite/binutils-all/objdump.Zs | 9 ++ binutils/testsuite/binutils-all/objdump.exp | 16 ++ binutils/testsuite/binutils-all/objdump.s | 1 + 8 files changed, 171 insertions(+), 149 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 57a8fa73ee3..d695d3b7496 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,27 @@ +2023-11-14 Nick Clifton + + PR 31062 + * objdump.c (decompressed_dumps): New local variable. + (usage): Mention the -z/--decompress option. + (long_options): Add --decompress. + (dump_section_header): Add "COMPRESSED" to the Flags field of any + compressed section. + (dump_section): Warn users when dumping a compressed section. + (display_any_bfd): Decompress the section if decompressed_dumps is + true. + (main): Handle the -z/--decompress option. + * NEWS: Mention the new feature. + * doc/binutils.texi: Document the new feature. + * testsuite/binutils-all/objdump.s: Update expected output. + * testsuite/binutils-all/objdump.exp: Add test of -Z -s. + * testsuite/binutils-all/objdump.Zs: New file. + + * readelf.c (maybe_expand_or_relocate_section): New function. + Contains common code found in dump functions. Adds a note message + if a compressed section is not being decompressed. + (dump_section_as_strings): Use new function. + (dump_section_as_bytes): Likewise. + 2023-11-10 Simon Marchi =20 * readelf.c (decode_AMDGPU_machine_flags): Handle gfx1100, diff --git a/binutils/NEWS b/binutils/NEWS index 1aae340ea2a..3bf3b568179 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -1,5 +1,13 @@ -*- text -*- =20 +* The objdump program has a new command line option -Z/--decompress which + changes the behaviour of the -s/--full-contents option, forcing it to + decompress the contents of any compressed section before they are displa= yed. + + In addition when objdump is displaying sections headers (via the -h/--he= aders + command line option) it will now display "COMPRESSED" in the Flags field= of + any compressed section. + * The readelf program has a new command line option --extra-sym-info which extends the information displayed by the --symbols option. When enabled the display will include the name of the section referenced by a symbol's diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index f94693631c7..ec23a78470e 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -2269,6 +2269,7 @@ objdump [@option{-a}|@option{--archive-headers}] [@option{-r}|@option{--reloc}] [@option{-R}|@option{--dynamic-reloc}] [@option{-s}|@option{--full-contents}] + [@option{-Z}|@option{--decompress}] [@option{-W[lLiaprmfFsoORtUuTgAck]}| @option{--dwarf}[=3Drawline,=3Ddecodedline,=3Dinfo,=3Dabbrev,=3Dp= ubnames,=3Daranges,=3Dmacro,=3Dframes,=3Dframes-interp,=3Dstr,=3Dstr-offset= s,=3Dloc,=3DRanges,=3Dpubtypes,=3Dtrace_info,=3Dtrace_abbrev,=3Dtrace_arang= es,=3Dgdb_index,=3Daddr,=3Dcu_index,=3Dlinks]] [@option{-WK}|@option{--dwarf=3Dfollow-links}] @@ -2800,7 +2801,10 @@ disassembly. @cindex object file sections Display the full contents of sections, often used in combination with @option{-j} to request specific sections. By default all non-empty -non-bss sections are displayed. +non-bss sections are displayed. By default any compressed section +will be displayed in its compressed form. In order to see the +contents in a decompressed form add the @option{-Z} option to the +command line. =20 @item -S @itemx --source @@ -3056,6 +3060,15 @@ Also do not truncate symbol names when they are disp= layed. Normally the disassembly output will skip blocks of zeroes. This option directs the disassembler to disassemble those blocks, just like any other data. + +@item -Z +@itemx --decompress +@cindex sections, full contents +@cindex object file sections +@cindex compressed section contents +The @option{-Z} option is meant to be used in conunction with the +@option{-s} option. It instructs @command{objdump} to decompress any +compressed sections before displaying their contents. @end table =20 @c man end diff --git a/binutils/objdump.c b/binutils/objdump.c index 60813426566..640ccb5dbc1 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -137,6 +137,7 @@ static bool color_output =3D false; /* --visualize-jump= s=3Dcolor. */ static bool extended_color_output =3D false; /* --visualize-jumps=3Dextend= ed-color. */ static int process_links =3D false; /* --process-links. */ static int show_all_symbols; /* --show-all-symbols. */ +static bool decompressed_dumps =3D false; /* -Z, --decompress. */ =20 static enum color_selection { @@ -278,6 +279,8 @@ usage (FILE *stream, int status) fprintf (stream, _("\ -s, --full-contents Display the full contents of all sections reque= sted\n")); fprintf (stream, _("\ + -Z, --decompress Decompress section(s) before displaying their c= ontents\n")); + fprintf (stream, _("\ -g, --debugging Display debug information in object file\n")); fprintf (stream, _("\ -e, --debugging-tags Display debug information using ctags style\n")= ); @@ -500,6 +503,7 @@ static struct option long_options[]=3D #endif {"debugging", no_argument, NULL, 'g'}, {"debugging-tags", no_argument, NULL, 'e'}, + {"decompress", no_argument, NULL, 'Z'}, {"demangle", optional_argument, NULL, 'C'}, {"disassemble", optional_argument, NULL, 'd'}, {"disassemble-all", no_argument, NULL, 'D'}, @@ -930,6 +934,9 @@ dump_section_header (bfd *abfd, asection *section, void= *data) comma =3D ", "; } =20 + if (bfd_is_section_compressed (abfd, section)) + printf ("%sCOMPRESSED", comma); + printf ("\n"); #undef PF } @@ -5024,6 +5031,9 @@ dump_section (bfd *abfd, asection *section, void *dum= my ATTRIBUTE_UNUSED) (unsigned long) (section->filepos + start_offset)); printf ("\n"); =20 + if (bfd_is_section_compressed (abfd, section) && ! decompressed_dumps) + printf (_(" NOTE: This section is compressed, but its contents have NO= T been expanded for this dump.\n")); + if (!bfd_get_full_section_contents (abfd, section, &data)) { non_fatal (_("Reading section %s failed because: %s"), @@ -5780,7 +5790,7 @@ static void display_any_bfd (bfd *file, int level) { /* Decompress sections unless dumping the section contents. */ - if (!dump_section_contents) + if (!dump_section_contents || decompressed_dumps) file->flags |=3D BFD_DECOMPRESS; =20 /* If the file is an archive, process all of its elements. */ @@ -5897,7 +5907,7 @@ main (int argc, char **argv) set_default_bfd_target (); =20 while ((c =3D getopt_long (argc, argv, - "CDE:FGHI:LM:P:RSTU:VW::ab:defghij:lm:prstvwxz", + "CDE:FGHI:LM:P:RSTU:VW::Zab:defghij:lm:prstvwxz", long_options, (int *) 0)) !=3D EOF) { @@ -5908,6 +5918,9 @@ main (int argc, char **argv) case 'm': machine =3D optarg; break; + case 'Z': + decompressed_dumps =3D true; + break; case 'M': { char *options; diff --git a/binutils/readelf.c b/binutils/readelf.c index 661ef0aab18..775106fb99c 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -15961,35 +15961,18 @@ uncompress_section_contents (bool is= _zstd, return false; } =20 -static bool -dump_section_as_strings (Elf_Internal_Shdr * section, Filedata * filedata) +static uint64_t +maybe_expand_or_relocate_section (Elf_Internal_Shdr * section, + Filedata * filedata, + unsigned char ** start_ptr, + bool relocate) { - Elf_Internal_Shdr *relsec; - uint64_t num_bytes; - unsigned char *data; - unsigned char *end; - unsigned char *real_start; - unsigned char *start; - bool some_strings_shown; - - real_start =3D start =3D (unsigned char *) get_section_contents (section= , filedata); - if (start =3D=3D NULL) - /* PR 21820: Do not fail if the section was empty. */ - return section->sh_size =3D=3D 0 || section->sh_type =3D=3D SHT_NOBITS; - - num_bytes =3D section->sh_size; - - if (filedata->is_separate) - printf (_("\nString dump of section '%s' in linked file %s:\n"), - printable_section_name (filedata, section), - filedata->file_name); - else - printf (_("\nString dump of section '%s':\n"), - printable_section_name (filedata, section)); - + uint64_t section_size =3D section->sh_size; + unsigned char * start =3D * start_ptr; + =20 if (decompress_dumps) { - uint64_t new_size =3D num_bytes; + uint64_t new_size =3D section_size; uint64_t uncompressed_size =3D 0; bool is_zstd =3D false; =20 @@ -15997,12 +15980,12 @@ dump_section_as_strings (Elf_Internal_Shdr * sect= ion, Filedata * filedata) { Elf_Internal_Chdr chdr; unsigned int compression_header_size - =3D get_compression_header (& chdr, (unsigned char *) start, - num_bytes); + =3D get_compression_header (& chdr, start, section_size); + if (compression_header_size =3D=3D 0) /* An error message will have already been generated by get_compression_header. */ - goto error_out; + return (uint64_t) -1; =20 if (chdr.ch_type =3D=3D ch_compress_zlib) ; @@ -16014,8 +15997,9 @@ dump_section_as_strings (Elf_Internal_Shdr * sectio= n, Filedata * filedata) { warn (_("section '%s' has unsupported compress type: %d\n"), printable_section_name (filedata, section), chdr.ch_type); - goto error_out; + return (uint64_t) -1; } + uncompressed_size =3D chdr.ch_size; start +=3D compression_header_size; new_size -=3D compression_header_size; @@ -16041,38 +16025,86 @@ dump_section_as_strings (Elf_Internal_Shdr * sect= ion, Filedata * filedata) { if (uncompress_section_contents (is_zstd, &start, uncompressed_size, &new_size, filedata->file_size)) - num_bytes =3D new_size; + section_size =3D new_size; else { error (_("Unable to decompress section %s\n"), printable_section_name (filedata, section)); - goto error_out; + return (uint64_t) -1; } } else - start =3D real_start; + start =3D * start_ptr; + } + else if (((section->sh_flags & SHF_COMPRESSED) !=3D 0) + || (section_size > 12 && streq ((char *) start, "ZLIB"))) + { + printf (_(" NOTE: This section is compressed, but its contents have = NOT been expanded for this dump.\n")); } =20 - /* If the section being dumped has relocations against it the user might - be expecting these relocations to have been applied. Check for this - case and issue a warning message in order to avoid confusion. - FIXME: Maybe we ought to have an option that dumps a section with - relocs applied ? */ - for (relsec =3D filedata->section_headers; - relsec < filedata->section_headers + filedata->file_header.e_shnum; - ++relsec) + if (relocate) { - if ((relsec->sh_type !=3D SHT_RELA && relsec->sh_type !=3D SHT_REL) - || relsec->sh_info >=3D filedata->file_header.e_shnum - || filedata->section_headers + relsec->sh_info !=3D section - || relsec->sh_size =3D=3D 0 - || relsec->sh_link >=3D filedata->file_header.e_shnum) - continue; + if (! apply_relocations (filedata, section, start, section_size, NUL= L, NULL)) + return (uint64_t) -1; + } + else + { + Elf_Internal_Shdr *relsec; =20 - printf (_(" Note: This section has relocations against it, but thes= e have NOT been applied to this dump.\n")); - break; + /* If the section being dumped has relocations against it the user m= ight + be expecting these relocations to have been applied. Check for this + case and issue a warning message in order to avoid confusion. + FIXME: Maybe we ought to have an option that dumps a section with + relocs applied ? */ + for (relsec =3D filedata->section_headers; + relsec < filedata->section_headers + filedata->file_header.e_shnum; + ++relsec) + { + if ((relsec->sh_type !=3D SHT_RELA && relsec->sh_type !=3D SHT_REL) + || relsec->sh_info >=3D filedata->file_header.e_shnum + || filedata->section_headers + relsec->sh_info !=3D section + || relsec->sh_size =3D=3D 0 + || relsec->sh_link >=3D filedata->file_header.e_shnum) + continue; + + printf (_(" NOTE: This section has relocations against it, but these ha= ve NOT been applied to this dump.\n")); + break; + } } =20 + * start_ptr =3D start; + return section_size; +} + +static bool +dump_section_as_strings (Elf_Internal_Shdr * section, Filedata * filedata) +{ + uint64_t num_bytes; + unsigned char *data; + unsigned char *end; + unsigned char *real_start; + unsigned char *start; + bool some_strings_shown; + + real_start =3D start =3D (unsigned char *) get_section_contents (section= , filedata); + if (start =3D=3D NULL) + /* PR 21820: Do not fail if the section was empty. */ + return section->sh_size =3D=3D 0 || section->sh_type =3D=3D SHT_NOBITS; + + num_bytes =3D section->sh_size; + + if (filedata->is_separate) + printf (_("\nString dump of section '%s' in linked file %s:\n"), + printable_section_name (filedata, section), + filedata->file_name); + else + printf (_("\nString dump of section '%s':\n"), + printable_section_name (filedata, section)); + + num_bytes =3D maybe_expand_or_relocate_section (section, filedata, & sta= rt, false); + if (num_bytes =3D=3D (uint64_t) -1) + goto error_out; + data =3D start; end =3D start + num_bytes; some_strings_shown =3D false; @@ -16187,7 +16219,6 @@ dump_section_as_bytes (Elf_Internal_Shdr *section, Filedata *filedata, bool relocate) { - Elf_Internal_Shdr *relsec; size_t bytes; uint64_t section_size; uint64_t addr; @@ -16210,102 +16241,9 @@ dump_section_as_bytes (Elf_Internal_Shdr *section, printf (_("\nHex dump of section '%s':\n"), printable_section_name (filedata, section)); =20 - if (decompress_dumps) - { - uint64_t new_size =3D section_size; - uint64_t uncompressed_size =3D 0; - bool is_zstd =3D false; - - if ((section->sh_flags & SHF_COMPRESSED) !=3D 0) - { - Elf_Internal_Chdr chdr; - unsigned int compression_header_size - =3D get_compression_header (& chdr, start, section_size); - - if (compression_header_size =3D=3D 0) - /* An error message will have already been generated - by get_compression_header. */ - goto error_out; - - if (chdr.ch_type =3D=3D ch_compress_zlib) - ; -#ifdef HAVE_ZSTD - else if (chdr.ch_type =3D=3D ch_compress_zstd) - is_zstd =3D true; -#endif - else - { - warn (_("section '%s' has unsupported compress type: %d\n"), - printable_section_name (filedata, section), chdr.ch_type); - goto error_out; - } - uncompressed_size =3D chdr.ch_size; - start +=3D compression_header_size; - new_size -=3D compression_header_size; - } - else if (new_size > 12 && streq ((char *) start, "ZLIB")) - { - /* Read the zlib header. In this case, it should be "ZLIB" - followed by the uncompressed section size, 8 bytes in - big-endian order. */ - uncompressed_size =3D start[4]; uncompressed_size <<=3D 8; - uncompressed_size +=3D start[5]; uncompressed_size <<=3D 8; - uncompressed_size +=3D start[6]; uncompressed_size <<=3D 8; - uncompressed_size +=3D start[7]; uncompressed_size <<=3D 8; - uncompressed_size +=3D start[8]; uncompressed_size <<=3D 8; - uncompressed_size +=3D start[9]; uncompressed_size <<=3D 8; - uncompressed_size +=3D start[10]; uncompressed_size <<=3D 8; - uncompressed_size +=3D start[11]; - start +=3D 12; - new_size -=3D 12; - } - - if (uncompressed_size) - { - if (uncompress_section_contents (is_zstd, &start, uncompressed_size, - &new_size, filedata->file_size)) - { - section_size =3D new_size; - } - else - { - error (_("Unable to decompress section %s\n"), - printable_section_name (filedata, section)); - /* FIXME: Print the section anyway ? */ - goto error_out; - } - } - else - start =3D real_start; - } - - if (relocate) - { - if (! apply_relocations (filedata, section, start, section_size, NUL= L, NULL)) - goto error_out; - } - else - { - /* If the section being dumped has relocations against it the user m= ight - be expecting these relocations to have been applied. Check for this - case and issue a warning message in order to avoid confusion. - FIXME: Maybe we ought to have an option that dumps a section with - relocs applied ? */ - for (relsec =3D filedata->section_headers; - relsec < filedata->section_headers + filedata->file_header.e_shnum; - ++relsec) - { - if ((relsec->sh_type !=3D SHT_RELA && relsec->sh_type !=3D SHT_REL) - || relsec->sh_info >=3D filedata->file_header.e_shnum - || filedata->section_headers + relsec->sh_info !=3D section - || relsec->sh_size =3D=3D 0 - || relsec->sh_link >=3D filedata->file_header.e_shnum) - continue; - - printf (_(" NOTE: This section has relocations against it, but these ha= ve NOT been applied to this dump.\n")); - break; - } - } + section_size =3D maybe_expand_or_relocate_section (section, filedata, & = start, relocate); + if (section_size =3D=3D (uint64_t) -1) + goto error_out; =20 addr =3D section->sh_addr; bytes =3D section_size; diff --git a/binutils/testsuite/binutils-all/objdump.Zs b/binutils/testsuit= e/binutils-all/objdump.Zs new file mode 100644 index 00000000000..32905b53a2c --- /dev/null +++ b/binutils/testsuite/binutils-all/objdump.Zs @@ -0,0 +1,9 @@ + +.*dw2-compressed.o: file format .* + +Contents of section .zdebug_abbrev: + 0000 01110110 06120111 01030825 08130b00 ...........%.... + 0010 00022e00 3f0c3a0b 3b0b0308 49131101 ....\?.:.;...I... + 0020 1201400a 00000324 0003080b 0b3e0b00 ..@....\$.....>.. + 0030 000000 ... =20 +#pass diff --git a/binutils/testsuite/binutils-all/objdump.exp b/binutils/testsui= te/binutils-all/objdump.exp index 4fe9e499d49..7071e965ca3 100644 --- a/binutils/testsuite/binutils-all/objdump.exp +++ b/binutils/testsuite/binutils-all/objdump.exp @@ -466,6 +466,22 @@ if { ![is_elf_format] } then { } else { pass "objdump -W" } + + # Test objdump -Z -s on a file that contains some compressed .debug se= ctions + + set got [remote_exec host "$OBJDUMP $OBJDUMPFLAGS -Z -s -j .zdebug_abb= rev $compressed_testfile" "" "/dev/null" "objdump.out"] + + if { [lindex $got 0] !=3D 0 || ![string match "" [lindex $got 1]] } th= en { + fail "objdump -Z -s (reason: unexpected output)" + send_log $got + send_log "\n" + } + + if { [regexp_diff objdump.out $srcdir/$subdir/objdump.Zs] } then { + fail "objdump -Z -s" + } else { + pass "objdump -Z -s" + } } =20 # Test objdump -WL on a file that contains line information for multiple f= iles and search directories. diff --git a/binutils/testsuite/binutils-all/objdump.s b/binutils/testsuite= /binutils-all/objdump.s index aea35dfa5a6..f80f8c54a61 100644 --- a/binutils/testsuite/binutils-all/objdump.s +++ b/binutils/testsuite/binutils-all/objdump.s @@ -2,6 +2,7 @@ .*dw2-compressed.o: file format .* =20 Contents of section .zdebug_abbrev: + NOTE: This section is compressed, but its contents have NOT been expanded= for this dump. 0000 5a4c4942 00000000 00000033 785e6314 ZLIB.......3x\^c. 0010 64146013 62146464 e650e510 e6666060 d.`.b.dd.P...f`` 0020 d263b0e7 b1e2b6e6 66e6f014 16641462 .c......f....d.b