public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v4 0/7] ELF: Strip section header in ELF objects
@ 2023-06-06 17:58 H.J. Lu
  2023-06-06 17:58 ` [PATCH v4 1/7] " H.J. Lu
                   ` (6 more replies)
  0 siblings, 7 replies; 17+ messages in thread
From: H.J. Lu @ 2023-06-06 17:58 UTC (permalink / raw)
  To: binutils; +Cc: Alan Modra, Florian Weimer, Kaylee Blake

Changes in v4:

1. Disallow -r with -z nosectionheader.
2. Add return after fail in no-section-header.exp.
3. Call free without checking null pointer.
4. Remove dead code.
5. Remove excess parentheses.

Changes in v3:

1. Fix indentation.
2. Update tests to allow extra symbols.
3. Limit ld-elf/hash-2.d to targets with shared library support.

Changes in v2:

1. Rename the objcopy and strip option to --strip-section-headers.
2. Also strip non-alloc sections.

Section header isn't mandatory on ELF executable nor shared library.
This patch set adds a new linker option, -z nosectionheader, to omit ELF
section header, a new objcopy and strip option, --strip-section-headers,
to remove ELF section header.

H.J. Lu (5):
  ELF: Discard non-alloc sections without section header
  bfd: Improve nm and objdump without section header
  binutils: Add a --strip-section-headers test
  ld: Add tests for -z nosectionheader and --strip-section-headers
  ld: Add -z nosectionheader test to bootstrap.exp

Kaylee Blake (2):
  ELF: Strip section header in ELF objects
  ld: Add simple tests for -z nosectionheader

 bfd/bfd-in2.h                                 |   6 +-
 bfd/bfd.c                                     |   6 +-
 bfd/elf-bfd.h                                 |  15 +
 bfd/elf.c                                     | 742 ++++++++++++++++--
 bfd/elfcode.h                                 |  91 ++-
 bfd/elflink.c                                 |  12 +
 bfd/elfxx-target.h                            |   4 +-
 binutils/NEWS                                 |   5 +-
 binutils/doc/binutils.texi                    |  10 +
 binutils/objcopy.c                            |  38 +-
 binutils/testsuite/binutils-all/objcopy.exp   |   5 +
 .../binutils-all/strip-section-headers-1.d    |   5 +
 ld/NEWS                                       |   3 +
 ld/emultempl/elf.em                           |   4 +
 ld/ld.h                                       |   3 +
 ld/ld.texi                                    |   5 +
 ld/ldlang.c                                   |   8 +
 ld/lexsup.c                                   |  13 +
 ld/testsuite/ld-bootstrap/bootstrap.exp       |  10 +-
 ld/testsuite/ld-elf/hash-2.d                  |  11 +
 ld/testsuite/ld-elf/no-section-header.exp     | 371 +++++++++
 ld/testsuite/ld-elf/nosectionheader-1.d       |  14 +
 ld/testsuite/ld-elf/nosectionheader-2.d       |   4 +
 ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.nd   |   3 +
 ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.rd   |  20 +
 .../ld-elf/pr25617-1-static-no-sec-hdr.rd     |  12 +
 ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd  |   3 +
 ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd  |  20 +
 ld/testsuite/ld-elf/pr25617-1a-sec-hdr.rd     |  19 +
 ld/testsuite/ld-elf/pr25617-1a.c              |  11 +
 ld/testsuite/ld-elf/pr25617-1b.c              |  15 +
 ld/testsuite/ld-elf/start-noheader.rd         |  11 +
 .../ld-elf/start-shared-noheader-gnu.rd       |  26 +
 .../ld-elf/start-shared-noheader-sysv.rd      |  26 +
 ld/testsuite/ld-elf/start-shared-noheader.nd  |  11 +
 35 files changed, 1475 insertions(+), 87 deletions(-)
 create mode 100644 binutils/testsuite/binutils-all/strip-section-headers-1.d
 create mode 100644 ld/testsuite/ld-elf/hash-2.d
 create mode 100644 ld/testsuite/ld-elf/no-section-header.exp
 create mode 100644 ld/testsuite/ld-elf/nosectionheader-1.d
 create mode 100644 ld/testsuite/ld-elf/nosectionheader-2.d
 create mode 100644 ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.nd
 create mode 100644 ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.rd
 create mode 100644 ld/testsuite/ld-elf/pr25617-1-static-no-sec-hdr.rd
 create mode 100644 ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd
 create mode 100644 ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd
 create mode 100644 ld/testsuite/ld-elf/pr25617-1a-sec-hdr.rd
 create mode 100644 ld/testsuite/ld-elf/pr25617-1a.c
 create mode 100644 ld/testsuite/ld-elf/pr25617-1b.c
 create mode 100644 ld/testsuite/ld-elf/start-noheader.rd
 create mode 100644 ld/testsuite/ld-elf/start-shared-noheader-gnu.rd
 create mode 100644 ld/testsuite/ld-elf/start-shared-noheader-sysv.rd
 create mode 100644 ld/testsuite/ld-elf/start-shared-noheader.nd

-- 
2.40.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v4 1/7] ELF: Strip section header in ELF objects
  2023-06-06 17:58 [PATCH v4 0/7] ELF: Strip section header in ELF objects H.J. Lu
@ 2023-06-06 17:58 ` H.J. Lu
  2023-06-06 17:58 ` [PATCH v4 2/7] ELF: Discard non-alloc sections without section header H.J. Lu
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 17+ messages in thread
From: H.J. Lu @ 2023-06-06 17:58 UTC (permalink / raw)
  To: binutils; +Cc: Alan Modra, Florian Weimer, Kaylee Blake

From: Kaylee Blake <klkblake@gmail.com>

Section header isn't mandatory on ELF executable nor shared library.
This patch adds a new linker option, -z nosectionheader, to omit ELF
section header, a new objcopy and strip option, --strip-section-headers,
to remove ELF section headers.

bfd/

2023-06-06  H.J. Lu  <hongjiu.lu@intel.com>
	    Kaylee Blake  <klkblake@gmail.com>

	PR ld/25617
	* bfd.c (BFD_NO_SECTION_HEADER): New.
	(BFD_FLAGS_SAVED): Add BFD_NO_SECTION_HEADER.
	(BFD_FLAGS_FOR_BFD_USE_MASK): Likewise.
	* elfcode.h (elf_swap_ehdr_out): Omit section header with
	BFD_NO_SECTION_HEADER.
	(elf_write_shdrs_and_ehdr): Likewise.
	* elfxx-target.h (TARGET_BIG_SYM): Add BFD_NO_SECTION_HEADER
	to object_flags.
	(TARGET_LITTLE_SYM): Likewise.
	* bfd-in2.h: Regenerated.

binutils/

2023-06-06  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/25617
	* NEWS: Mention --strip-section-headers for objcopy and strip.
	* objcopy.c (strip_section_headers): New.
	(command_line_switch): Add OPTION_STRIP_SECTION_HEADERS.
	(strip_options): Add --strip-section-headers.
	(copy_options): Likewise.
	(copy_usage): Add --strip-section-headers.
	(strip_usage): Likewise.
	(copy_object): Handle --strip-section-headers for ELF files.
	(strip_main): Handle OPTION_STRIP_SECTION_HEADERS.
	(copy_main): Likewise.
	* doc/binutils.texi: Document --strip-section-headers for objcopy
	and strip.

ld/

2023-06-06  H.J. Lu  <hongjiu.lu@intel.com>
	    Kaylee Blake  <klkblake@gmail.com>

	PR ld/25617
	* NEWS: Mention -z nosectionheader.
	* emultempl/elf.em: Support -z sectionheader and
	-z nosectionheader.
	* ld.h (ld_config_type): Add no_section_header.
	* ld.texi: Document -z sectionheader and -z nosectionheader.
	* ldlang.c (ldlang_open_output): Handle
	config.no_section_header.
	* lexsup.c (parse_args): Enable --strip-all with
	-z nosectionheader.  Disallow -r with -z nosectionheader.
	(elf_static_list_options): Add -z sectionheader and
	-z nosectionheader.
---
 bfd/bfd-in2.h              |  6 +++++-
 bfd/bfd.c                  |  6 +++++-
 bfd/elfcode.h              | 36 ++++++++++++++++++++++++++----------
 bfd/elfxx-target.h         |  4 ++--
 binutils/NEWS              |  5 ++++-
 binutils/doc/binutils.texi | 10 ++++++++++
 binutils/objcopy.c         | 33 +++++++++++++++++++++++++++++++--
 ld/NEWS                    |  3 +++
 ld/emultempl/elf.em        |  4 ++++
 ld/ld.h                    |  3 +++
 ld/ld.texi                 |  5 +++++
 ld/ldlang.c                |  4 ++++
 ld/lexsup.c                | 13 +++++++++++++
 13 files changed, 115 insertions(+), 17 deletions(-)

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 6f8a8fd114d..a84a3c24f2a 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -2048,11 +2048,15 @@ struct bfd
   /* Compress sections in this BFD with SHF_COMPRESSED zstd.  */
 #define BFD_COMPRESS_ZSTD      0x400000
 
+  /* Don't generate ELF section header.  */
+#define BFD_NO_SECTION_HEADER  0x800000
+
   /* Flags bits which are for BFD use only.  */
 #define BFD_FLAGS_FOR_BFD_USE_MASK \
   (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
    | BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT \
-   | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON | BFD_USE_ELF_STT_COMMON)
+   | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON | BFD_USE_ELF_STT_COMMON \
+   | BFD_NO_SECTION_HEADER)
 
   /* The format which belongs to the BFD. (object, core, etc.)  */
   ENUM_BITFIELD (bfd_format) format : 3;
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 4ae73701ce1..9c4e4174acd 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -192,11 +192,15 @@ CODE_FRAGMENT
 .  {* Compress sections in this BFD with SHF_COMPRESSED zstd.  *}
 .#define BFD_COMPRESS_ZSTD      0x400000
 .
+.  {* Don't generate ELF section header.  *}
+.#define BFD_NO_SECTION_HEADER	0x800000
+.
 .  {* Flags bits which are for BFD use only.  *}
 .#define BFD_FLAGS_FOR_BFD_USE_MASK \
 .  (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
 .   | BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT \
-.   | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON | BFD_USE_ELF_STT_COMMON)
+.   | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON | BFD_USE_ELF_STT_COMMON \
+.   | BFD_NO_SECTION_HEADER)
 .
 .  {* The format which belongs to the BFD. (object, core, etc.)  *}
 .  ENUM_BITFIELD (bfd_format) format : 3;
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index e4e29f0dc57..495e498838d 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -266,6 +266,7 @@ elf_swap_ehdr_out (bfd *abfd,
 {
   unsigned int tmp;
   int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
+  bool no_section_header = (abfd->flags & BFD_NO_SECTION_HEADER) != 0;
   memcpy (dst->e_ident, src->e_ident, EI_NIDENT);
   /* note that all elements of dst are *arrays of unsigned char* already...  */
   H_PUT_16 (abfd, src->e_type, dst->e_type);
@@ -276,7 +277,10 @@ elf_swap_ehdr_out (bfd *abfd,
   else
     H_PUT_WORD (abfd, src->e_entry, dst->e_entry);
   H_PUT_WORD (abfd, src->e_phoff, dst->e_phoff);
-  H_PUT_WORD (abfd, src->e_shoff, dst->e_shoff);
+  if (no_section_header)
+    H_PUT_WORD (abfd, 0, dst->e_shoff);
+  else
+    H_PUT_WORD (abfd, src->e_shoff, dst->e_shoff);
   H_PUT_32 (abfd, src->e_flags, dst->e_flags);
   H_PUT_16 (abfd, src->e_ehsize, dst->e_ehsize);
   H_PUT_16 (abfd, src->e_phentsize, dst->e_phentsize);
@@ -284,15 +288,24 @@ elf_swap_ehdr_out (bfd *abfd,
   if (tmp > PN_XNUM)
     tmp = PN_XNUM;
   H_PUT_16 (abfd, tmp, dst->e_phnum);
-  H_PUT_16 (abfd, src->e_shentsize, dst->e_shentsize);
-  tmp = src->e_shnum;
-  if (tmp >= (SHN_LORESERVE & 0xffff))
-    tmp = SHN_UNDEF;
-  H_PUT_16 (abfd, tmp, dst->e_shnum);
-  tmp = src->e_shstrndx;
-  if (tmp >= (SHN_LORESERVE & 0xffff))
-    tmp = SHN_XINDEX & 0xffff;
-  H_PUT_16 (abfd, tmp, dst->e_shstrndx);
+  if (no_section_header)
+    {
+      H_PUT_16 (abfd, 0, dst->e_shentsize);
+      H_PUT_16 (abfd, 0, dst->e_shnum);
+      H_PUT_16 (abfd, 0, dst->e_shstrndx);
+    }
+  else
+    {
+      H_PUT_16 (abfd, src->e_shentsize, dst->e_shentsize);
+      tmp = src->e_shnum;
+      if (tmp >= (SHN_LORESERVE & 0xffff))
+	tmp = SHN_UNDEF;
+      H_PUT_16 (abfd, tmp, dst->e_shnum);
+      tmp = src->e_shstrndx;
+      if (tmp >= (SHN_LORESERVE & 0xffff))
+	tmp = SHN_XINDEX & 0xffff;
+      H_PUT_16 (abfd, tmp, dst->e_shstrndx);
+    }
 }
 
 /* Translate an ELF section header table entry in external format into an
@@ -1077,6 +1090,9 @@ elf_write_shdrs_and_ehdr (bfd *abfd)
       || bfd_bwrite (&x_ehdr, amt, abfd) != amt)
     return false;
 
+  if ((abfd->flags & BFD_NO_SECTION_HEADER) != 0)
+    return true;
+
   /* Some fields in the first section header handle overflow of ehdr
      fields.  */
   if (i_ehdrp->e_phnum >= PN_XNUM)
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index 9bcbdfb27dd..20191fae294 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -994,7 +994,7 @@ const bfd_target TARGET_BIG_SYM =
   (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS
    | DYNAMIC | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS
    | BFD_COMPRESS_GABI | BFD_COMPRESS_ZSTD | BFD_CONVERT_ELF_COMMON
-   | BFD_USE_ELF_STT_COMMON),
+   | BFD_USE_ELF_STT_COMMON | BFD_NO_SECTION_HEADER),
 
   /* section_flags: mask of all section flags */
   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY
@@ -1099,7 +1099,7 @@ const bfd_target TARGET_LITTLE_SYM =
   (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS
    | DYNAMIC | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS
    | BFD_COMPRESS_GABI | BFD_COMPRESS_ZSTD | BFD_CONVERT_ELF_COMMON
-   | BFD_USE_ELF_STT_COMMON),
+   | BFD_USE_ELF_STT_COMMON | BFD_NO_SECTION_HEADER),
 
   /* section_flags: mask of all section flags */
   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY
diff --git a/binutils/NEWS b/binutils/NEWS
index b29f36bf1d4..bb614a14503 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -2,7 +2,10 @@
 
 * Objdump's --private option can now be used on PE format files to display the
   fields in the file header and section headers.
-  
+
+* Add command-line option, --strip-section-headers, to objcopy and strip to
+  remove ELF section header from ELF file.
+
 Changes in 2.40:
 
 * Objdump has a new command line option --show-all-symbols which will make it
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 8c14d1121d9..8314cb57562 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -1278,6 +1278,7 @@ objcopy [@option{-F} @var{bfdname}|@option{--target=}@var{bfdname}]
         [@option{-R} @var{sectionpattern}|@option{--remove-section=}@var{sectionpattern}]
         [@option{--keep-section=}@var{sectionpattern}]
         [@option{--remove-relocations=}@var{sectionpattern}]
+        [@option{--strip-section-headers}]
         [@option{-p}|@option{--preserve-dates}]
         [@option{-D}|@option{--enable-deterministic-archives}]
         [@option{-U}|@option{--disable-deterministic-archives}]
@@ -1494,6 +1495,10 @@ will remove all relocations for sections matching the pattern
 '.text.*', but will not remove relocations for the section
 '.text.foo'.
 
+@item --strip-section-headers
+Strip section header   This option is specific to ELF files.
+Implies @option{--strip-all} and @option{--merge-notes}.
+
 @item -S
 @itemx --strip-all
 Do not copy relocation and symbol information from the source file.
@@ -3484,6 +3489,7 @@ strip [@option{-F} @var{bfdname} |@option{--target=}@var{bfdname}]
       [@option{-R} @var{sectionname} |@option{--remove-section=}@var{sectionname}]
       [@option{--keep-section=}@var{sectionpattern}]
       [@option{--remove-relocations=}@var{sectionpattern}]
+      [@option{--strip-section-headers}]
       [@option{-o} @var{file}] [@option{-p}|@option{--preserve-dates}]
       [@option{-D}|@option{--enable-deterministic-archives}]
       [@option{-U}|@option{--disable-deterministic-archives}]
@@ -3586,6 +3592,10 @@ will remove all relocations for sections matching the pattern
 '.text.*', but will not remove relocations for the section
 '.text.foo'.
 
+@item --strip-section-headers
+Strip section headers.  This option is specific to ELF files.  Implies
+@option{--strip-all} and @option{--merge-notes}.
+
 @item -s
 @itemx --strip-all
 Remove all symbols.
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index ac40da87018..6112bbb9bdb 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -97,6 +97,7 @@ static int deterministic = -1;		/* Enable deterministic archives.  */
 static int status = 0;			/* Exit status.  */
 
 static bool    merge_notes = false;	/* Merge note sections.  */
+static bool strip_section_headers = false;/* Strip section headers.  */
 
 typedef struct merged_note_section
 {
@@ -365,6 +366,7 @@ enum command_line_switch
   OPTION_SREC_LEN,
   OPTION_STACK,
   OPTION_STRIP_DWO,
+  OPTION_STRIP_SECTION_HEADERS,
   OPTION_STRIP_SYMBOLS,
   OPTION_STRIP_UNNEEDED,
   OPTION_STRIP_UNNEEDED_SYMBOL,
@@ -403,6 +405,7 @@ static struct option strip_options[] =
   {"preserve-dates", no_argument, 0, 'p'},
   {"remove-section", required_argument, 0, 'R'},
   {"remove-relocations", required_argument, 0, OPTION_REMOVE_RELOCS},
+  {"strip-section-headers", no_argument, 0, OPTION_STRIP_SECTION_HEADERS},
   {"strip-all", no_argument, 0, 's'},
   {"strip-debug", no_argument, 0, 'S'},
   {"strip-dwo", no_argument, 0, OPTION_STRIP_DWO},
@@ -492,6 +495,7 @@ static struct option copy_options[] =
   {"remove-leading-char", no_argument, 0, OPTION_REMOVE_LEADING_CHAR},
   {"remove-section", required_argument, 0, 'R'},
   {"remove-relocations", required_argument, 0, OPTION_REMOVE_RELOCS},
+  {"strip-section-headers", no_argument, 0, OPTION_STRIP_SECTION_HEADERS},
   {"rename-section", required_argument, 0, OPTION_RENAME_SECTION},
   {"reverse-bytes", required_argument, 0, OPTION_REVERSE_BYTES},
   {"section-alignment", required_argument, 0, OPTION_PE_SECTION_ALIGNMENT},
@@ -592,6 +596,7 @@ copy_usage (FILE *stream, int exit_status)
      --add-gnu-debuglink=<file>    Add section .gnu_debuglink linking to <file>\n\
   -R --remove-section <name>       Remove section <name> from the output\n\
      --remove-relocations <name>   Remove relocations from section <name>\n\
+     --strip-section-headers              Strip section header from the output\n\
   -S --strip-all                   Remove all symbol and relocation information\n\
   -g --strip-debug                 Remove all debugging symbols & sections\n\
      --strip-dwo                   Remove all DWO sections\n\
@@ -730,6 +735,7 @@ strip_usage (FILE *stream, int exit_status)
   fprintf (stream, _("\
   -R --remove-section=<name>       Also remove section <name> from the output\n\
      --remove-relocations <name>   Remove relocations from section <name>\n\
+     --strip-section-headers       Strip section headers from the output\n\
   -s --strip-all                   Remove all symbol and relocation information\n\
   -g -S -d --strip-debug           Remove all debugging symbols & sections\n\
      --strip-dwo                   Remove all DWO sections\n\
@@ -2695,7 +2701,16 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
      necessary.  */
   VerilogDataEndianness = ibfd->xvec->byteorder;
 
-  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
+  if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour)
+    {
+      if (strip_section_headers)
+	{
+	  ibfd->flags |= BFD_NO_SECTION_HEADER;
+	  strip_symbols = STRIP_ALL;
+	  merge_notes = true;
+	}
+    }
+  else
     {
       if ((do_debug_sections & compress) != 0
 	  && do_debug_sections != compress)
@@ -2712,6 +2727,13 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
 		     bfd_get_archive_filename (ibfd));
 	  return false;
 	}
+
+      if (strip_section_headers)
+	{
+	  non_fatal (_("--strip_section_headers is unsupported on `%s'"),
+		     bfd_get_archive_filename (ibfd));
+	  return false;
+	}
     }
 
   if (verbose)
@@ -3456,7 +3478,7 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
 	  free (merged);
 	}
     }
-  else if (merge_notes && ! is_strip)
+  else if (merge_notes && ! is_strip && ! strip_section_headers)
     non_fatal (_("%s: Could not find any mergeable note sections"),
 	       bfd_get_filename (ibfd));
 
@@ -4754,6 +4776,9 @@ strip_main (int argc, char *argv[])
 	case OPTION_REMOVE_RELOCS:
 	  handle_remove_relocations_option (optarg);
 	  break;
+	case OPTION_STRIP_SECTION_HEADERS:
+	  strip_section_headers = true;
+	  break;
 	case 's':
 	  strip_symbols = STRIP_ALL;
 	  break;
@@ -5223,6 +5248,10 @@ copy_main (int argc, char *argv[])
 	  handle_remove_relocations_option (optarg);
 	  break;
 
+	case OPTION_STRIP_SECTION_HEADERS:
+	  strip_section_headers = true;
+	  break;
+
 	case 'S':
 	  strip_symbols = STRIP_ALL;
 	  break;
diff --git a/ld/NEWS b/ld/NEWS
index 9920d0209b8..0a471107516 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -10,6 +10,9 @@
 * The linker script syntax has a new command for output sections: ASCIZ "string"
   This will insert a zero-terminated string at the current location.
 
+* Add command-line option, -z nosectionheader, to omit ELF section
+  header.
+
 Changes in 2.40:
 
 * The linker has a new command line option to suppress the generation of any
diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em
index e367299146f..3f67f8b09d9 100644
--- a/ld/emultempl/elf.em
+++ b/ld/emultempl/elf.em
@@ -807,6 +807,10 @@ fragment <<EOF
 		     "must be default, internal, hidden, or protected"),
 		   optarg);
 	}
+      else if (strcmp (optarg, "sectionheader") == 0)
+	config.no_section_header = false;
+      else if (strcmp (optarg, "nosectionheader") == 0)
+	config.no_section_header = true;
 EOF
 
 if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
diff --git a/ld/ld.h b/ld/ld.h
index 1882a282020..a0f8a15c7a9 100644
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -280,6 +280,9 @@ typedef struct
   /* If set, code and non-code sections should never be in one segment.  */
   bool separate_code;
 
+  /* If set, generation of ELF section header should be suppressed.  */
+  bool no_section_header;
+
   /* The rpath separation character.  Usually ':'.  */
   char rpath_separator;
 
diff --git a/ld/ld.texi b/ld/ld.texi
index 5639de797de..55eda164d2d 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -1484,6 +1484,11 @@ Don't create an ELF @code{PT_GNU_RELRO} segment if @samp{norelro}.
 Report dynamic relative relocations generated by linker.  Supported for
 Linux/i386 and Linux/x86_64.
 
+@item sectionheader
+@itemx nosectionheader
+Generate section header.  Don't generate section header if
+@samp{nosectionheader} is used.  @option{sectionheader} is the default.
+
 @item separate-code
 @itemx noseparate-code
 Create separate code @code{PT_LOAD} segment header in the object.  This
diff --git a/ld/ldlang.c b/ld/ldlang.c
index a9c4a4d5bd7..43ff43339a2 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -3416,6 +3416,10 @@ ldlang_open_output (lang_statement_union_type *statement)
 	link_info.output_bfd->flags |= BFD_TRADITIONAL_FORMAT;
       else
 	link_info.output_bfd->flags &= ~BFD_TRADITIONAL_FORMAT;
+      if (config.no_section_header)
+	link_info.output_bfd->flags |= BFD_NO_SECTION_HEADER;
+      else
+	link_info.output_bfd->flags &= ~BFD_NO_SECTION_HEADER;
       break;
 
     case lang_target_statement_enum:
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 6090921bda4..1a0b5ecd609 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -1971,6 +1971,15 @@ parse_args (unsigned argc, char **argv)
 	break;
       }
 
+  /* -z nosectionheader implies --strip-all.  */
+  if (config.no_section_header)
+    {
+      if (bfd_link_relocatable (&link_info))
+	einfo (_("%F%P: -r and -z nosectionheader may not be used together\n"));
+
+      link_info.strip = strip_all;
+    }
+
   if (!bfd_link_dll (&link_info))
     {
       if (command_line.filter_shlib)
@@ -2245,6 +2254,10 @@ elf_static_list_options (FILE *file)
   fprintf (file, _("\
   -z start-stop-visibility=V  Set visibility of built-in __start/__stop symbols\n\
                                 to DEFAULT, PROTECTED, HIDDEN or INTERNAL\n"));
+  fprintf (file, _("\
+  -z sectionheader            Generate section header (default)\n"));
+  fprintf (file, _("\
+  -z nosectionheader          Do not generate section header\n"));
 }
 
 static void
-- 
2.40.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v4 2/7] ELF: Discard non-alloc sections without section header
  2023-06-06 17:58 [PATCH v4 0/7] ELF: Strip section header in ELF objects H.J. Lu
  2023-06-06 17:58 ` [PATCH v4 1/7] " H.J. Lu
@ 2023-06-06 17:58 ` H.J. Lu
  2023-06-06 17:58 ` [PATCH v4 3/7] bfd: Improve nm and objdump " H.J. Lu
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 17+ messages in thread
From: H.J. Lu @ 2023-06-06 17:58 UTC (permalink / raw)
  To: binutils; +Cc: Alan Modra, Florian Weimer, Kaylee Blake

Discard non-alloc sections when section headers are stripped.

bfd/

	PR ld/25617
	* elf.c (_bfd_elf_assign_file_positions_for_non_load): Skip
	non-load sections without section header.
	(_bfd_elf_write_object_contents): Don't set the sh_name field
	without section header.  Write out the .shstrtab section only
	if its sh_offset field isn't -1.

binutils/

	PR ld/25617
	* objcopy.c (is_strip_section_1): Remove non-alloc sections for
	--strip-section-headers.

ld/

	PR ld/25617
	* ldlang.c (lang_discard_section_p): Discard non-alloc sections
	if we are stripping section headers.
---
 bfd/elf.c          | 13 ++++++++++---
 binutils/objcopy.c |  7 ++++++-
 ld/ldlang.c        |  4 ++++
 3 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/bfd/elf.c b/bfd/elf.c
index 81eb3ef71fa..07ad15ddb2f 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -6597,6 +6597,10 @@ _bfd_elf_assign_file_positions_for_non_load (bfd *abfd)
   Elf_Internal_Ehdr *i_ehdrp;
   const struct elf_backend_data *bed;
 
+  /* Skip non-load sections without section header.  */
+  if ((abfd->flags & BFD_NO_SECTION_HEADER) != 0)
+    return true;
+
   off = elf_next_file_pos (abfd);
 
   shdrpp = elf_elfsections (abfd);
@@ -6720,9 +6724,11 @@ _bfd_elf_write_object_contents (bfd *abfd)
   num_sec = elf_numsections (abfd);
   for (count = 1; count < num_sec; count++)
     {
-      i_shdrp[count]->sh_name
-	= _bfd_elf_strtab_offset (elf_shstrtab (abfd),
-				  i_shdrp[count]->sh_name);
+      /* Don't set the sh_name field without section header.  */
+      if ((abfd->flags & BFD_NO_SECTION_HEADER) == 0)
+	i_shdrp[count]->sh_name
+	  = _bfd_elf_strtab_offset (elf_shstrtab (abfd),
+				    i_shdrp[count]->sh_name);
       if (bed->elf_backend_section_processing)
 	if (!(*bed->elf_backend_section_processing) (abfd, i_shdrp[count]))
 	  return false;
@@ -6739,6 +6745,7 @@ _bfd_elf_write_object_contents (bfd *abfd)
   /* Write out the section header names.  */
   t = elf_tdata (abfd);
   if (elf_shstrtab (abfd) != NULL
+      && t->shstrtab_hdr.sh_offset != -1
       && (bfd_seek (abfd, t->shstrtab_hdr.sh_offset, SEEK_SET) != 0
 	  || !_bfd_elf_strtab_emit (abfd, elf_shstrtab (abfd))))
     return false;
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index 6112bbb9bdb..9d6f31b4909 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -1377,6 +1377,11 @@ is_strip_section_1 (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
 	return true;
     }
 
+  /* Remove non-alloc sections for --strip-section-headers.  */
+  if (strip_section_headers
+      && (bfd_section_flags (sec) & SEC_ALLOC) == 0)
+    return true;
+
   if ((bfd_section_flags (sec) & SEC_DEBUGGING) != 0)
     {
       if (strip_symbols == STRIP_DEBUG
@@ -2730,7 +2735,7 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
 
       if (strip_section_headers)
 	{
-	  non_fatal (_("--strip_section_headers is unsupported on `%s'"),
+	  non_fatal (_("--strip-section-headers is unsupported on `%s'"),
 		     bfd_get_archive_filename (ibfd));
 	  return false;
 	}
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 43ff43339a2..740fdb4ce2f 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -2520,6 +2520,10 @@ lang_discard_section_p (asection *section)
       && (flags & SEC_DEBUGGING) != 0)
     discard = true;
 
+  /* Discard non-alloc sections if we are stripping section headers.  */
+  else if (config.no_section_header && (flags & SEC_ALLOC) == 0)
+    discard = true;
+
   return discard;
 }
 
-- 
2.40.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v4 3/7] bfd: Improve nm and objdump without section header
  2023-06-06 17:58 [PATCH v4 0/7] ELF: Strip section header in ELF objects H.J. Lu
  2023-06-06 17:58 ` [PATCH v4 1/7] " H.J. Lu
  2023-06-06 17:58 ` [PATCH v4 2/7] ELF: Discard non-alloc sections without section header H.J. Lu
@ 2023-06-06 17:58 ` H.J. Lu
  2023-07-01  2:12   ` Simon Marchi
  2023-06-06 17:58 ` [PATCH v4 4/7] ld: Add simple tests for -z nosectionheader H.J. Lu
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: H.J. Lu @ 2023-06-06 17:58 UTC (permalink / raw)
  To: binutils; +Cc: Alan Modra, Florian Weimer, Kaylee Blake

When there is no section header in an executable or shared library, we
reconstruct dynamic symbol table from the PT_DYNAMIC segment, which
contains DT_HASH/DT_GNU_HASH/DT_MIPS_XHASH, DT_STRTAB, DT_SYMTAB,
DT_STRSZ, and DT_SYMENT entries, to improve nm and objdump.  For DT_HASH,
the number of dynamic symbol table entries equals the number of chains.
For DT_GNU_HASH/DT_MIPS_XHASH, only defined symbols with non-STB_LOCAL
indings are in hash table.  Since DT_GNU_HASH/DT_MIPS_XHASH place all
symbols with STB_LOCAL binding before symbols with other bindings and
all undefined symbols defined ones in dynamic symbol table, the highest
symbol index in DT_GNU_HASH/DT_MIPS_XHASH is the highest dynamic symbol
table index.  We can also get symbol version from DT_VERSYM, DT_VERDEF
and DT_VERNEED entries.

dt_symtab, dt_versym, dt_verdef, dt_verneed, dt_symtab_count,
dt_verdef_count, dt_verneed_count and dt_strtab are added to
elf_obj_tdata to store dynamic symbol table information.

	PR ld/25617
	* elf-bfd.h (elf_obj_tdata): Add dt_symtab, dt_verdef, dt_verneed,
	dt_symtab_count, dt_verdef_count, dt_verneed_count and dt_strtab.
	(elf_use_dt_symtab_p): New.
	(_bfd_elf_get_dynamic_symbols): Likewise.
	(_bfd_elf_get_section_from_dynamic_symbol): Likewise.
	* elf.c (bfd_elf_get_elf_syms): Use dynamic symbol table if
	neeeded.
	(_bfd_elf_get_dynamic_symtab_upper_bound): Likewise.
	(_bfd_elf_slurp_version_tables): Likewise.
	(offset_from_vma): New function.
	(get_hash_table_data): Likewise.
	(_bfd_elf_get_dynamic_symbols): Likewise.
	(_bfd_elf_get_section_from_dynamic_symbol): Likewise.
	(_bfd_elf_get_symbol_version_name): Likewise.
	* elfcode.h (elf_object_p): Call _bfd_elf_get_dynamic_symbols
	to reconstruct dynamic symbol table from PT_DYNAMIC segment if
	there is no section header.
	(elf_slurp_symbol_table): Use dynamic symbol table if neeeded.
	Don't free isymbuf when dynamic symbol table is used.
	* elflink.c (elf_link_is_defined_archive_symbol): Return wrong
	format error when dynamic symbol table is used.
	(elf_link_add_object_symbols): Likewise.
---
 bfd/elf-bfd.h |  15 ++
 bfd/elf.c     | 729 ++++++++++++++++++++++++++++++++++++++++++++++----
 bfd/elfcode.h |  55 +++-
 bfd/elflink.c |  12 +
 4 files changed, 746 insertions(+), 65 deletions(-)

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 2a64a1e6a03..dd8d6efbbcc 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2031,6 +2031,14 @@ struct elf_obj_tdata
   Elf_Internal_Shdr dynversym_hdr;
   Elf_Internal_Shdr dynverref_hdr;
   Elf_Internal_Shdr dynverdef_hdr;
+  Elf_Internal_Sym *dt_symtab;
+  bfd_byte *dt_versym;
+  bfd_byte *dt_verdef;
+  bfd_byte *dt_verneed;
+  size_t dt_symtab_count;
+  size_t dt_verdef_count;
+  size_t dt_verneed_count;
+  char *dt_strtab;
   elf_section_list * symtab_shndx_list;
   bfd_vma gp;				/* The gp value */
   unsigned int gp_size;			/* The gp size */
@@ -2194,6 +2202,7 @@ struct elf_obj_tdata
 #define elf_dyn_lib_class(bfd)	(elf_tdata(bfd) -> dyn_lib_class)
 #define elf_bad_symtab(bfd)	(elf_tdata(bfd) -> bad_symtab)
 #define elf_flags_init(bfd)	(elf_tdata(bfd) -> o->flags_init)
+#define elf_use_dt_symtab_p(bfd) (elf_tdata(bfd) -> dt_symtab_count != 0)
 #define elf_known_obj_attributes(bfd) (elf_tdata (bfd) -> known_obj_attributes)
 #define elf_other_obj_attributes(bfd) (elf_tdata (bfd) -> other_obj_attributes)
 #define elf_known_obj_attributes_proc(bfd) \
@@ -2587,6 +2596,12 @@ extern bfd_reloc_status_type bfd_elf_perform_complex_relocation
 extern bool _bfd_elf_setup_sections
   (bfd *);
 
+extern bool _bfd_elf_get_dynamic_symbols
+  (bfd *, Elf_Internal_Phdr *, Elf_Internal_Phdr *, size_t,
+   bfd_size_type);
+extern asection *_bfd_elf_get_section_from_dynamic_symbol
+  (bfd *, Elf_Internal_Sym *);
+
 extern struct bfd_link_hash_entry *bfd_elf_define_start_stop
   (struct bfd_link_info *, const char *, asection *);
 
diff --git a/bfd/elf.c b/bfd/elf.c
index 07ad15ddb2f..29d05e47786 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -397,6 +397,17 @@ bfd_elf_get_elf_syms (bfd *ibfd,
   if (symcount == 0)
     return intsym_buf;
 
+  if (elf_use_dt_symtab_p (ibfd))
+    {
+      /* Use dynamic symbol table.  */
+      if (elf_tdata (ibfd)->dt_symtab_count != symcount + symoffset)
+	{
+	  bfd_set_error (bfd_error_invalid_operation);
+	  return NULL;
+	}
+      return elf_tdata (ibfd)->dt_symtab + symoffset;
+    }
+
   /* Normal syms might have section extension entries.  */
   shndx_hdr = NULL;
   if (elf_symtab_shndx_list (ibfd) != NULL)
@@ -1873,6 +1884,551 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
   return false;
 }
 
+/* Find the file offset corresponding to VMA by using the program
+   headers.  */
+
+static file_ptr
+offset_from_vma (Elf_Internal_Phdr *phdrs, size_t phnum, bfd_vma vma,
+		 size_t size, size_t *max_size_p)
+{
+  Elf_Internal_Phdr *seg;
+  size_t i;
+
+  for (seg = phdrs, i = 0; i < phnum; ++seg, ++i)
+    if (seg->p_type == PT_LOAD
+	&& vma >= (seg->p_vaddr & -seg->p_align)
+	&& vma + size <= seg->p_vaddr + seg->p_filesz)
+      {
+	if (max_size_p)
+	  *max_size_p = seg->p_vaddr + seg->p_filesz - vma;
+	return vma - seg->p_vaddr + seg->p_offset;
+      }
+
+  bfd_set_error (bfd_error_invalid_operation);
+  return (file_ptr) -1;
+}
+
+/* Convert hash table to internal form.  */
+
+static bfd_vma *
+get_hash_table_data (bfd *abfd, bfd_size_type number,
+		     unsigned int ent_size, bfd_size_type filesize)
+{
+  unsigned char *e_data = NULL;
+  bfd_vma *i_data = NULL;
+  bfd_size_type size;
+
+  if (ent_size != 4 && ent_size != 8)
+    return NULL;
+
+  if ((size_t) number != number)
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return NULL;
+    }
+
+  size = ent_size * number;
+  /* Be kind to memory checkers (eg valgrind, address sanitizer) by not
+     attempting to allocate memory when the read is bound to fail.  */
+  if (size > filesize
+      || number >= ~(size_t) 0 / ent_size
+      || number >= ~(size_t) 0 / sizeof (*i_data))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return NULL;
+    }
+
+  e_data = _bfd_malloc_and_read (abfd, size, size);
+  if (e_data == NULL)
+    return NULL;
+
+  i_data = (bfd_vma *) bfd_malloc (number * sizeof (*i_data));
+  if (i_data == NULL)
+    {
+      free (e_data);
+      return NULL;
+    }
+
+  if (ent_size == 4)
+    while (number--)
+      i_data[number] = bfd_get_32 (abfd, e_data + number * ent_size);
+  else
+    while (number--)
+      i_data[number] = bfd_get_64 (abfd, e_data + number * ent_size);
+
+  free (e_data);
+  return i_data;
+}
+
+/* Address of .MIPS.xhash section.  FIXME: What is the best way to
+   support DT_MIPS_XHASH?  */
+#define DT_MIPS_XHASH	       0x70000036
+
+/* Reconstruct dynamic symbol table from PT_DYNAMIC segment.  */
+
+bool
+_bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
+			      Elf_Internal_Phdr *phdrs, size_t phnum,
+			      bfd_size_type filesize)
+{
+  bfd_byte *extdyn, *extdynend;
+  size_t extdynsize;
+  void (*swap_dyn_in) (bfd *, const void *, Elf_Internal_Dyn *);
+  bool (*swap_symbol_in) (bfd *, const void *, const void *,
+			  Elf_Internal_Sym *);
+  Elf_Internal_Dyn dyn;
+  bfd_vma dt_hash = 0;
+  bfd_vma dt_gnu_hash = 0;
+  bfd_vma dt_mips_xhash = 0;
+  bfd_vma dt_strtab = 0;
+  bfd_vma dt_symtab = 0;
+  size_t dt_strsz = 0;
+  bfd_vma dt_versym = 0;
+  bfd_vma dt_verdef = 0;
+  bfd_vma dt_verneed = 0;
+  bfd_byte *dynbuf = NULL;
+  char *strbuf = NULL;
+  bfd_vma *gnubuckets = NULL;
+  bfd_vma *gnuchains = NULL;
+  bfd_vma *mipsxlat = NULL;
+  file_ptr saved_filepos, filepos;
+  bool res = false;
+  size_t amt;
+  bfd_byte *esymbuf = NULL, *esym;
+  bfd_size_type symcount;
+  Elf_Internal_Sym *isymbuf = NULL;
+  Elf_Internal_Sym *isym, *isymend;
+  bfd_byte *versym = NULL;
+  bfd_byte *verdef = NULL;
+  bfd_byte *verneed = NULL;
+  size_t verdef_size;
+  size_t verneed_size;
+  size_t extsym_size;
+  const struct elf_backend_data *bed;
+
+  /* Return TRUE if symbol table is bad.  */
+  if (elf_bad_symtab (abfd))
+    return true;
+
+  /* Return TRUE if DT_HASH/DT_GNU_HASH have bee processed before.  */
+  if (elf_tdata (abfd)->dt_strtab != NULL)
+    return true;
+
+  bed = get_elf_backend_data (abfd);
+
+  /* Save file position for elf_object_p.  */
+  saved_filepos = bfd_tell (abfd);
+
+  if (bfd_seek (abfd, phdr->p_offset, SEEK_SET) != 0)
+    goto error_return;
+
+  dynbuf = _bfd_malloc_and_read (abfd, phdr->p_filesz, phdr->p_filesz);
+  if (dynbuf == NULL)
+    goto error_return;
+
+  extsym_size = bed->s->sizeof_sym;
+  extdynsize = bed->s->sizeof_dyn;
+  swap_dyn_in = bed->s->swap_dyn_in;
+
+  extdyn = dynbuf;
+  if (phdr->p_filesz < extdynsize)
+    goto error_return;
+  extdynend = extdyn + phdr->p_filesz;
+  for (; extdyn <= (extdynend - extdynsize); extdyn += extdynsize)
+    {
+      swap_dyn_in (abfd, extdyn, &dyn);
+
+      if (dyn.d_tag == DT_NULL)
+	break;
+
+      switch (dyn.d_tag)
+	{
+	case DT_HASH:
+	  dt_hash = dyn.d_un.d_val;
+	  break;
+	case DT_GNU_HASH:
+	  if (bed->elf_machine_code != EM_MIPS
+	      && bed->elf_machine_code != EM_MIPS_RS3_LE)
+	    dt_gnu_hash = dyn.d_un.d_val;
+	  break;
+	case DT_STRTAB:
+	  dt_strtab = dyn.d_un.d_val;
+	  break;
+	case DT_SYMTAB:
+	  dt_symtab = dyn.d_un.d_val;
+	  break;
+	case DT_STRSZ:
+	  dt_strsz = dyn.d_un.d_val;
+	  break;
+	case DT_SYMENT:
+	  if (dyn.d_un.d_val != extsym_size)
+	    goto error_return;
+	  break;
+	case DT_VERSYM:
+	  dt_versym = dyn.d_un.d_val;
+	  break;
+	case DT_VERDEF:
+	  dt_verdef = dyn.d_un.d_val;
+	  break;
+	case DT_VERNEED:
+	  dt_verneed = dyn.d_un.d_val;
+	  break;
+	default:
+	  if (dyn.d_tag == DT_MIPS_XHASH
+	      && (bed->elf_machine_code == EM_MIPS
+		  || bed->elf_machine_code == EM_MIPS_RS3_LE))
+	    {
+	      dt_gnu_hash = dyn.d_un.d_val;
+	      dt_mips_xhash = dyn.d_un.d_val;
+	    }
+	  break;
+	}
+    }
+
+  /* Check if we can reconstruct dynamic symbol table from PT_DYNAMIC
+     segment.  */
+  if ((!dt_hash && !dt_gnu_hash)
+      || !dt_strtab
+      || !dt_symtab
+      || !dt_strsz)
+    goto error_return;
+
+  /* Get dynamic string table.  */
+  filepos = offset_from_vma (phdrs, phnum, dt_strtab, dt_strsz, NULL);
+  if (filepos == (file_ptr) -1
+      || bfd_seek (abfd, filepos, SEEK_SET) != 0)
+    goto error_return;
+
+  /* Dynamic string table must be valid until ABFD is closed.  */
+  strbuf = (char *) _bfd_alloc_and_read (abfd, dt_strsz, dt_strsz);
+  if (strbuf == NULL)
+    goto error_return;
+
+  /* Get the real symbol count from DT_HASH or DT_GNU_HASH.  Prefer
+     DT_HASH since it is simpler than DT_GNU_HASH.  */
+  if (dt_hash)
+    {
+      unsigned char nb[16];
+      unsigned int hash_ent_size;
+
+      switch (bed->elf_machine_code)
+	{
+	case EM_ALPHA:
+	case EM_S390:
+	case EM_S390_OLD:
+	  if (bed->s->elfclass == ELFCLASS64)
+	    {
+	      hash_ent_size = 8;
+	      break;
+	    }
+	  /* FALLTHROUGH */
+	default:
+	  hash_ent_size = 4;
+	  break;
+	}
+
+      filepos = offset_from_vma (phdrs, phnum, dt_hash, sizeof (nb),
+				 NULL);
+      if (filepos == (file_ptr) -1
+	  || bfd_seek (abfd, filepos, SEEK_SET) != 0
+	  || (bfd_bread (nb, 2 * hash_ent_size, abfd)
+	      != (2 * hash_ent_size)))
+	goto error_return;
+
+      /* The number of dynamic symbol table entries equals the number
+	 of chains.  */
+      if (hash_ent_size == 8)
+	symcount = bfd_get_64 (abfd, nb + hash_ent_size);
+      else
+	symcount = bfd_get_32 (abfd, nb + hash_ent_size);
+    }
+  else
+    {
+      /* For DT_GNU_HASH, only defined symbols with non-STB_LOCAL
+	 bindings are in hash table.  Since in dynamic symbol table,
+	 all symbols with STB_LOCAL binding are placed before symbols
+	 with other bindings and all undefined symbols are placed
+	 before defined ones, the highest symbol index in DT_GNU_HASH
+	 is the highest dynamic symbol table index.  */
+      unsigned char nb[16];
+      bfd_vma ngnubuckets;
+      bfd_vma gnusymidx;
+      size_t i, ngnuchains;
+      bfd_vma maxchain = 0xffffffff, bitmaskwords;
+      bfd_vma buckets_vma;
+
+      filepos = offset_from_vma (phdrs, phnum, dt_gnu_hash,
+				 sizeof (nb), NULL);
+      if (filepos == (file_ptr) -1
+	  || bfd_seek (abfd, filepos, SEEK_SET) != 0
+	  || bfd_bread (nb, sizeof (nb), abfd) != sizeof (nb))
+	goto error_return;
+
+      ngnubuckets = bfd_get_32 (abfd, nb);
+      gnusymidx = bfd_get_32 (abfd, nb + 4);
+      bitmaskwords = bfd_get_32 (abfd, nb + 8);
+      buckets_vma = dt_gnu_hash + 16;
+      if (bed->s->elfclass == ELFCLASS32)
+	buckets_vma += bitmaskwords * 4;
+      else
+	buckets_vma += bitmaskwords * 8;
+      filepos = offset_from_vma (phdrs, phnum, buckets_vma, 4, NULL);
+      if (filepos == (file_ptr) -1
+	  || bfd_seek (abfd, filepos, SEEK_SET) != 0)
+	goto error_return;
+
+      gnubuckets = get_hash_table_data (abfd, ngnubuckets, 4, filesize);
+      if (gnubuckets == NULL)
+	goto error_return;
+
+      for (i = 0; i < ngnubuckets; i++)
+	if (gnubuckets[i] != 0)
+	  {
+	    if (gnubuckets[i] < gnusymidx)
+	      goto error_return;
+
+	    if (maxchain == 0xffffffff || gnubuckets[i] > maxchain)
+	      maxchain = gnubuckets[i];
+	  }
+
+      if (maxchain == 0xffffffff)
+	{
+	  symcount = 0;
+	  goto empty_gnu_hash;
+	}
+
+      maxchain -= gnusymidx;
+      filepos = offset_from_vma (phdrs, phnum,
+				 (buckets_vma +
+				  4 * (ngnubuckets + maxchain)),
+				 4, NULL);
+      if (filepos == (file_ptr) -1
+	  || bfd_seek (abfd, filepos, SEEK_SET) != 0)
+	goto error_return;
+
+      do
+	{
+	  if (bfd_bread (nb, 4, abfd) != 4)
+	    goto error_return;
+	  ++maxchain;
+	  if (maxchain == 0)
+	    goto error_return;
+	}
+      while ((bfd_get_32 (abfd, nb) & 1) == 0);
+
+      filepos = offset_from_vma (phdrs, phnum,
+				 (buckets_vma + 4 * ngnubuckets),
+				 4, NULL);
+      if (filepos == (file_ptr) -1
+	  || bfd_seek (abfd, filepos, SEEK_SET) != 0)
+	goto error_return;
+
+      gnuchains = get_hash_table_data (abfd, maxchain, 4, filesize);
+      if (gnubuckets == NULL)
+	goto error_return;
+      ngnuchains = maxchain;
+
+      if (dt_mips_xhash)
+	{
+	  filepos = offset_from_vma (phdrs, phnum,
+				     (buckets_vma
+				      + 4 * (ngnubuckets + maxchain)),
+				     4, NULL);
+	  if (filepos == (file_ptr) -1
+	      || bfd_seek (abfd, filepos, SEEK_SET) != 0)
+	    goto error_return;
+
+	  mipsxlat = get_hash_table_data (abfd, maxchain, 4, filesize);
+	  if (mipsxlat == NULL)
+	    goto error_return;
+	}
+
+      symcount = 0;
+      for (i = 0; i < ngnubuckets; ++i)
+	if (gnubuckets[i] != 0)
+	  {
+	    bfd_vma si = gnubuckets[i];
+	    bfd_vma off = si - gnusymidx;
+	    do
+	      {
+		if (mipsxlat)
+		  {
+		    if (mipsxlat[off] >= symcount)
+		      symcount = mipsxlat[off] + 1;
+		  }
+		else
+		  {
+		    if (si >= symcount)
+		      symcount = si + 1;
+		  }
+		si++;
+	      }
+	    while (off < ngnuchains && (gnuchains[off++] & 1) == 0);
+	  }
+    }
+
+  /* Swap in dynamic symbol table.  */
+  if (_bfd_mul_overflow (symcount, extsym_size, &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      goto error_return;
+    }
+
+  filepos = offset_from_vma (phdrs, phnum, dt_symtab, amt, NULL);
+  if (filepos == (file_ptr) -1
+      || bfd_seek (abfd, filepos, SEEK_SET) != 0)
+    goto error_return;
+  esymbuf = _bfd_malloc_and_read (abfd, amt, amt);
+  if (esymbuf == NULL)
+    goto error_return;
+
+  if (_bfd_mul_overflow (symcount, sizeof (Elf_Internal_Sym), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      goto error_return;
+    }
+
+  /* Dynamic symbol table must be valid until ABFD is closed.  */
+  isymbuf = (Elf_Internal_Sym *) bfd_alloc (abfd, amt);
+  if (isymbuf == NULL)
+    goto error_return;
+
+  swap_symbol_in = bed->s->swap_symbol_in;
+
+  /* Convert the symbols to internal form.  */
+  isymend = isymbuf + symcount;
+  for (esym = esymbuf, isym = isymbuf;
+       isym < isymend;
+       esym += extsym_size, isym++)
+    if (!swap_symbol_in (abfd, esym, NULL, isym)
+	|| isym->st_name >= dt_strsz)
+      {
+	bfd_set_error (bfd_error_invalid_operation);
+	goto error_return;
+      }
+
+  if (dt_versym)
+    {
+      /* Swap in DT_VERSYM.  */
+      if (_bfd_mul_overflow (symcount, 2, &amt))
+	{
+	  bfd_set_error (bfd_error_file_too_big);
+	  goto error_return;
+	}
+
+      filepos = offset_from_vma (phdrs, phnum, dt_versym, amt, NULL);
+      if (filepos == (file_ptr) -1
+	  || bfd_seek (abfd, filepos, SEEK_SET) != 0)
+	goto error_return;
+
+      /* DT_VERSYM info must be valid until ABFD is closed.  */
+      versym = _bfd_alloc_and_read (abfd, amt, amt);
+
+      if (dt_verdef)
+	{
+	  /* Read in DT_VERDEF.  */
+	  filepos = offset_from_vma (phdrs, phnum, dt_verdef,
+				     0, &verdef_size);
+	  if (filepos == (file_ptr) -1
+	      || bfd_seek (abfd, filepos, SEEK_SET) != 0)
+	    goto error_return;
+
+	  /* DT_VERDEF info must be valid until ABFD is closed.  */
+	  verdef = _bfd_alloc_and_read (abfd, verdef_size,
+					verdef_size);
+	}
+
+      if (dt_verneed)
+	{
+	  /* Read in DT_VERNEED.  */
+	  filepos = offset_from_vma (phdrs, phnum, dt_verneed,
+				     0, &verneed_size);
+	  if (filepos == (file_ptr) -1
+	      || bfd_seek (abfd, filepos, SEEK_SET) != 0)
+	    goto error_return;
+
+	  /* DT_VERNEED info must be valid until ABFD is closed.  */
+	  verneed = _bfd_alloc_and_read (abfd, verneed_size,
+					 verneed_size);
+	}
+    }
+
+ empty_gnu_hash:
+  elf_tdata (abfd)->dt_strtab = strbuf;
+  elf_tdata (abfd)->dt_symtab = isymbuf;
+  elf_tdata (abfd)->dt_symtab_count = symcount;
+  elf_tdata (abfd)->dt_versym = versym;
+  elf_tdata (abfd)->dt_verdef = verdef;
+  elf_tdata (abfd)->dt_verneed = verneed;
+  elf_tdata (abfd)->dt_verdef_count
+    = verdef_size / sizeof (Elf_External_Verdef);
+  elf_tdata (abfd)->dt_verneed_count
+    = verneed_size / sizeof (Elf_External_Verneed);
+
+  res = true;
+
+ error_return:
+  /* Restore file position for elf_object_p.  */
+  if (bfd_seek (abfd, saved_filepos, SEEK_SET) != 0)
+    res = false;
+  free (dynbuf);
+  free (esymbuf);
+  free (gnubuckets);
+  free (gnuchains);
+  free (mipsxlat);
+  return res;
+}
+
+/* Reconstruct section from dynamic symbol.  */
+
+asection *
+_bfd_elf_get_section_from_dynamic_symbol (bfd *abfd,
+					  Elf_Internal_Sym *isym)
+{
+  asection *sec;
+  flagword flags;
+
+  if (!elf_use_dt_symtab_p (abfd))
+    return NULL;
+
+  flags = SEC_ALLOC | SEC_LOAD;
+  switch (ELF_ST_TYPE (isym->st_info))
+    {
+    case STT_FUNC:
+    case STT_GNU_IFUNC:
+      sec = bfd_get_section_by_name (abfd, ".text");
+      if (sec == NULL)
+	sec = bfd_make_section_with_flags (abfd,
+					   ".text",
+					   flags | SEC_CODE);
+      break;
+    case STT_COMMON:
+      sec = bfd_com_section_ptr;
+      break;
+    case STT_OBJECT:
+      sec = bfd_get_section_by_name (abfd, ".data");
+      if (sec == NULL)
+	sec = bfd_make_section_with_flags (abfd,
+					   ".data",
+					   flags | SEC_DATA);
+      break;
+    case STT_TLS:
+      sec = bfd_get_section_by_name (abfd, ".tdata");
+      if (sec == NULL)
+	sec = bfd_make_section_with_flags (abfd,
+					   ".tdata",
+					   (flags
+					    | SEC_DATA
+					    | SEC_THREAD_LOCAL));
+      break;
+    default:
+      sec = bfd_abs_section_ptr;
+      break;
+    }
+
+  return sec;
+}
+
 /* Get version name.  If BASE_P is TRUE, return "Base" for VER_FLG_BASE
    and return symbol version for symbol version itself.   */
 
@@ -1882,8 +2438,11 @@ _bfd_elf_get_symbol_version_string (bfd *abfd, asymbol *symbol,
 				    bool *hidden)
 {
   const char *version_string = NULL;
-  if (elf_dynversym (abfd) != 0
-      && (elf_dynverdef (abfd) != 0 || elf_dynverref (abfd) != 0))
+  if ((elf_dynversym (abfd) != 0
+       && (elf_dynverdef (abfd) != 0 || elf_dynverref (abfd) != 0))
+      || (elf_tdata (abfd)->dt_versym != NULL
+	  && (elf_tdata (abfd)->dt_verdef != NULL
+	      || elf_tdata (abfd)->dt_verneed != NULL)))
     {
       unsigned int vernum = ((elf_symbol_type *) symbol)->version;
 
@@ -8609,6 +9168,11 @@ _bfd_elf_get_dynamic_symtab_upper_bound (bfd *abfd)
 
   if (elf_dynsymtab (abfd) == 0)
     {
+      /* Check if there is dynamic symbol table.  */
+      symcount = elf_tdata (abfd)->dt_symtab_count;
+      if (symcount)
+	goto compute_symtab_size;
+
       bfd_set_error (bfd_error_invalid_operation);
       return -1;
     }
@@ -8619,6 +9183,8 @@ _bfd_elf_get_dynamic_symtab_upper_bound (bfd *abfd)
       bfd_set_error (bfd_error_file_too_big);
       return -1;
     }
+
+ compute_symtab_size:
   symtab_size = symcount * (sizeof (asymbol *));
   if (symcount == 0)
     symtab_size = sizeof (asymbol *);
@@ -8826,35 +9392,51 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
   unsigned int freeidx = 0;
   size_t amt;
 
-  if (elf_dynverref (abfd) != 0)
+  if (elf_dynverref (abfd) != 0 || elf_tdata (abfd)->dt_verneed != NULL)
     {
       Elf_Internal_Shdr *hdr;
       Elf_External_Verneed *everneed;
       Elf_Internal_Verneed *iverneed;
       unsigned int i;
       bfd_byte *contents_end;
+      size_t verneed_count;
+      size_t verneed_size;
 
-      hdr = &elf_tdata (abfd)->dynverref_hdr;
-
-      if (hdr->sh_info > hdr->sh_size / sizeof (Elf_External_Verneed))
+      if (elf_tdata (abfd)->dt_verneed != NULL)
 	{
-	error_return_bad_verref:
-	  _bfd_error_handler
-	    (_("%pB: .gnu.version_r invalid entry"), abfd);
-	  bfd_set_error (bfd_error_bad_value);
-	error_return_verref:
-	  elf_tdata (abfd)->verref = NULL;
-	  elf_tdata (abfd)->cverrefs = 0;
-	  goto error_return;
+	  hdr = NULL;
+	  contents = elf_tdata (abfd)->dt_verneed;
+	  verneed_count = elf_tdata (abfd)->dt_verneed_count;
+	  verneed_size = verneed_count * sizeof (Elf_External_Verneed);
 	}
+      else
+	{
+	  hdr = &elf_tdata (abfd)->dynverref_hdr;
 
-      if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0)
-	goto error_return_verref;
-      contents = _bfd_malloc_and_read (abfd, hdr->sh_size, hdr->sh_size);
-      if (contents == NULL)
-	goto error_return_verref;
+	  if (hdr->sh_info > hdr->sh_size / sizeof (Elf_External_Verneed))
+	    {
+	    error_return_bad_verref:
+	      _bfd_error_handler
+		(_("%pB: .gnu.version_r invalid entry"), abfd);
+	      bfd_set_error (bfd_error_bad_value);
+	    error_return_verref:
+	      elf_tdata (abfd)->verref = NULL;
+	      elf_tdata (abfd)->cverrefs = 0;
+	      goto error_return;
+	    }
+
+	  if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0)
+	    goto error_return_verref;
+	  contents = _bfd_malloc_and_read (abfd, hdr->sh_size, hdr->sh_size);
+	  if (contents == NULL)
+	    goto error_return_verref;
+
+	  verneed_size = hdr->sh_size;
+	  verneed_count = hdr->sh_info;
+	}
 
-      if (_bfd_mul_overflow (hdr->sh_info, sizeof (Elf_Internal_Verneed), &amt))
+      if (_bfd_mul_overflow (verneed_count,
+			     sizeof (Elf_Internal_Verneed), &amt))
 	{
 	  bfd_set_error (bfd_error_file_too_big);
 	  goto error_return_verref;
@@ -8867,10 +9449,11 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
 
       BFD_ASSERT (sizeof (Elf_External_Verneed)
 		  == sizeof (Elf_External_Vernaux));
-      contents_end = contents + hdr->sh_size - sizeof (Elf_External_Verneed);
+      contents_end = (contents + verneed_size
+		      - sizeof (Elf_External_Verneed));
       everneed = (Elf_External_Verneed *) contents;
       iverneed = elf_tdata (abfd)->verref;
-      for (i = 0; i < hdr->sh_info; i++, iverneed++)
+      for (i = 0; i < verneed_count; i++, iverneed++)
 	{
 	  Elf_External_Vernaux *evernaux;
 	  Elf_Internal_Vernaux *ivernaux;
@@ -8880,9 +9463,13 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
 
 	  iverneed->vn_bfd = abfd;
 
-	  iverneed->vn_filename =
-	    bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
-					     iverneed->vn_file);
+	  if (elf_use_dt_symtab_p (abfd))
+	    iverneed->vn_filename
+	      = elf_tdata (abfd)->dt_strtab + iverneed->vn_file;
+	  else
+	    iverneed->vn_filename
+	      = bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
+						 iverneed->vn_file);
 	  if (iverneed->vn_filename == NULL)
 	    goto error_return_bad_verref;
 
@@ -8913,9 +9500,13 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
 	    {
 	      _bfd_elf_swap_vernaux_in (abfd, evernaux, ivernaux);
 
-	      ivernaux->vna_nodename =
-		bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
-						 ivernaux->vna_name);
+	      if (elf_use_dt_symtab_p (abfd))
+		ivernaux->vna_nodename
+		  = elf_tdata (abfd)->dt_strtab + ivernaux->vna_name;
+	      else
+		ivernaux->vna_nodename
+		  = bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
+						     ivernaux->vna_name);
 	      if (ivernaux->vna_nodename == NULL)
 		goto error_return_bad_verref;
 
@@ -8954,11 +9545,12 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
 	}
       elf_tdata (abfd)->cverrefs = i;
 
-      free (contents);
+      if (elf_tdata (abfd)->dt_verneed == NULL)
+	free (contents);
       contents = NULL;
     }
 
-  if (elf_dynverdef (abfd) != 0)
+  if (elf_dynverdef (abfd) != 0 || elf_tdata (abfd)->dt_verdef != NULL)
     {
       Elf_Internal_Shdr *hdr;
       Elf_External_Verdef *everdef;
@@ -8968,40 +9560,56 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
       unsigned int i;
       unsigned int maxidx;
       bfd_byte *contents_end_def, *contents_end_aux;
+      size_t verdef_count;
+      size_t verdef_size;
 
-      hdr = &elf_tdata (abfd)->dynverdef_hdr;
-
-      if (hdr->sh_size < sizeof (Elf_External_Verdef))
+      if (elf_tdata (abfd)->dt_verdef != NULL)
 	{
-	error_return_bad_verdef:
-	  _bfd_error_handler
-	    (_("%pB: .gnu.version_d invalid entry"), abfd);
-	  bfd_set_error (bfd_error_bad_value);
-	error_return_verdef:
-	  elf_tdata (abfd)->verdef = NULL;
-	  elf_tdata (abfd)->cverdefs = 0;
-	  goto error_return;
+	  hdr = NULL;
+	  contents = elf_tdata (abfd)->dt_verdef;
+	  verdef_count = elf_tdata (abfd)->dt_verdef_count;
+	  verdef_size = verdef_count * sizeof (Elf_External_Verdef);
 	}
+      else
+	{
+	  hdr = &elf_tdata (abfd)->dynverdef_hdr;
 
-      if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0)
-	goto error_return_verdef;
-      contents = _bfd_malloc_and_read (abfd, hdr->sh_size, hdr->sh_size);
-      if (contents == NULL)
-	goto error_return_verdef;
+	  if (hdr->sh_size < sizeof (Elf_External_Verdef))
+	    {
+	    error_return_bad_verdef:
+	      _bfd_error_handler
+		(_("%pB: .gnu.version_d invalid entry"), abfd);
+	      bfd_set_error (bfd_error_bad_value);
+	    error_return_verdef:
+	      elf_tdata (abfd)->verdef = NULL;
+	      elf_tdata (abfd)->cverdefs = 0;
+	      goto error_return;
+	    }
+
+	  if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0)
+	    goto error_return_verdef;
+	  contents = _bfd_malloc_and_read (abfd, hdr->sh_size, hdr->sh_size);
+	  if (contents == NULL)
+	    goto error_return_verdef;
 
-      BFD_ASSERT (sizeof (Elf_External_Verdef)
-		  >= sizeof (Elf_External_Verdaux));
-      contents_end_def = contents + hdr->sh_size
-			 - sizeof (Elf_External_Verdef);
-      contents_end_aux = contents + hdr->sh_size
-			 - sizeof (Elf_External_Verdaux);
+	  BFD_ASSERT (sizeof (Elf_External_Verdef)
+		      >= sizeof (Elf_External_Verdaux));
+
+	  verdef_count = hdr->sh_info;
+	  verdef_size = hdr->sh_size;
+	}
+
+      contents_end_def = (contents + verdef_size
+			  - sizeof (Elf_External_Verdef));
+      contents_end_aux = (contents + verdef_size
+			  - sizeof (Elf_External_Verdaux));
 
       /* We know the number of entries in the section but not the maximum
 	 index.  Therefore we have to run through all entries and find
 	 the maximum.  */
       everdef = (Elf_External_Verdef *) contents;
       maxidx = 0;
-      for (i = 0; i < hdr->sh_info; ++i)
+      for (i = 0; i < verdef_count; ++i)
 	{
 	  _bfd_elf_swap_verdef_in (abfd, everdef, &iverdefmem);
 
@@ -9044,7 +9652,7 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
 
       everdef = (Elf_External_Verdef *) contents;
       iverdefarr = elf_tdata (abfd)->verdef;
-      for (i = 0; i < hdr->sh_info; i++)
+      for (i = 0; i < verdef_count; ++i)
 	{
 	  Elf_External_Verdaux *everdaux;
 	  Elf_Internal_Verdaux *iverdaux;
@@ -9087,9 +9695,13 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
 	    {
 	      _bfd_elf_swap_verdaux_in (abfd, everdaux, iverdaux);
 
-	      iverdaux->vda_nodename =
-		bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
-						 iverdaux->vda_name);
+	      if (elf_use_dt_symtab_p (abfd))
+		iverdaux->vda_nodename
+		  = elf_tdata (abfd)->dt_strtab + iverdaux->vda_name;
+	      else
+		iverdaux->vda_nodename
+		  = bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
+						     iverdaux->vda_name);
 	      if (iverdaux->vda_nodename == NULL)
 		goto error_return_bad_verdef;
 
@@ -9124,7 +9736,8 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
 		     ((bfd_byte *) everdef + iverdef->vd_next));
 	}
 
-      free (contents);
+      if (elf_tdata (abfd)->dt_verdef == NULL)
+	free (contents);
       contents = NULL;
     }
   else if (default_imported_symver)
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index 495e498838d..aae66bcebf8 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -839,6 +839,21 @@ elf_object_p (bfd *abfd)
 		  abfd->read_only = 1;
 		}
 	    }
+	  if (i_phdr->p_filesz != 0)
+	    {
+	      if ((i_phdr->p_offset + i_phdr->p_filesz) > filesize)
+		goto got_no_match;
+	      /* Try to reconstruct dynamic symbol table from PT_DYNAMIC
+		 segment if there is no section header.  */
+	      if (i_phdr->p_type == PT_DYNAMIC
+		  && i_ehdrp->e_shstrndx == 0
+		  && i_ehdrp->e_shoff == 0
+		  && !_bfd_elf_get_dynamic_symbols (abfd, i_phdr,
+						    elf_tdata (abfd)->phdr,
+						    i_ehdrp->e_phnum,
+						    filesize))
+		goto got_no_match;
+	    }
 	}
     }
 
@@ -1245,7 +1260,9 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bool dynamic)
       if ((elf_dynverdef (abfd) != 0
 	   && elf_tdata (abfd)->verdef == NULL)
 	  || (elf_dynverref (abfd) != 0
-	      && elf_tdata (abfd)->verref == NULL))
+	      && elf_tdata (abfd)->verref == NULL)
+	  || elf_tdata (abfd)->dt_verdef != NULL
+	  || elf_tdata (abfd)->dt_verneed != NULL)
 	{
 	  if (!_bfd_elf_slurp_version_tables (abfd, false))
 	    return -1;
@@ -1253,11 +1270,15 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bool dynamic)
     }
 
   ebd = get_elf_backend_data (abfd);
-  symcount = hdr->sh_size / sizeof (Elf_External_Sym);
+  symcount = elf_tdata (abfd)->dt_symtab_count;
+  if (symcount == 0)
+    symcount = hdr->sh_size / sizeof (Elf_External_Sym);
   if (symcount == 0)
     sym = symbase = NULL;
   else
     {
+      size_t i;
+
       isymbuf = bfd_elf_get_elf_syms (abfd, hdr, symcount, 0,
 				      NULL, NULL, NULL);
       if (isymbuf == NULL)
@@ -1304,12 +1325,18 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bool dynamic)
       if (xver != NULL)
 	++xver;
       isymend = isymbuf + symcount;
-      for (isym = isymbuf + 1, sym = symbase; isym < isymend; isym++, sym++)
+      for (isym = isymbuf + 1, sym = symbase, i = 1;
+	   isym < isymend;
+	   isym++, sym++, i++)
 	{
 	  memcpy (&sym->internal_elf_sym, isym, sizeof (Elf_Internal_Sym));
 
 	  sym->symbol.the_bfd = abfd;
-	  sym->symbol.name = bfd_elf_sym_name (abfd, hdr, isym, NULL);
+	  if (elf_use_dt_symtab_p (abfd))
+	    sym->symbol.name = (elf_tdata (abfd)->dt_strtab
+				+ isym->st_name);
+	  else
+	    sym->symbol.name = bfd_elf_sym_name (abfd, hdr, isym, NULL);
 	  sym->symbol.value = isym->st_value;
 
 	  if (isym->st_shndx == SHN_UNDEF)
@@ -1343,6 +1370,15 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bool dynamic)
 		 moment) about the alignment.  */
 	      sym->symbol.value = isym->st_size;
 	    }
+	  else if (elf_use_dt_symtab_p (abfd))
+	    {
+	      asection *sec;
+	      sec = _bfd_elf_get_section_from_dynamic_symbol (abfd,
+							      isym);
+	      if (sec == NULL)
+		goto error_return;
+	      sym->symbol.section = sec;
+	    }
 	  else
 	    {
 	      sym->symbol.section
@@ -1423,7 +1459,10 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bool dynamic)
 	  if (dynamic)
 	    sym->symbol.flags |= BSF_DYNAMIC;
 
-	  if (xver != NULL)
+	  if (elf_tdata (abfd)->dt_versym)
+	    sym->version = bfd_get_16 (abfd,
+				       elf_tdata (abfd)->dt_versym + 2 * i);
+	  else if (xver != NULL)
 	    {
 	      Elf_Internal_Versym iversym;
 
@@ -1461,13 +1500,15 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bool dynamic)
     }
 
   free (xverbuf);
-  if (hdr->contents != (unsigned char *) isymbuf)
+  if (hdr->contents != (unsigned char *) isymbuf
+      && !elf_use_dt_symtab_p (abfd))
     free (isymbuf);
   return symcount;
 
  error_return:
   free (xverbuf);
-  if (hdr->contents != (unsigned char *) isymbuf)
+  if (hdr->contents != (unsigned char *) isymbuf
+      && !elf_use_dt_symtab_p (abfd))
     free (isymbuf);
   return -1;
 }
diff --git a/bfd/elflink.c b/bfd/elflink.c
index f10faa5f8bd..422c7b25c81 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -3571,6 +3571,12 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
   if (! bfd_check_format (abfd, bfd_object))
     return false;
 
+  if (elf_use_dt_symtab_p (abfd))
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return false;
+    }
+
   /* Select the appropriate symbol table.  If we don't know if the
      object file is an IR object, give linker LTO plugin a chance to
      get the correct symbol table.  */
@@ -4233,6 +4239,12 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   htab = elf_hash_table (info);
   bed = get_elf_backend_data (abfd);
 
+  if (elf_use_dt_symtab_p (abfd))
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return false;
+    }
+
   if ((abfd->flags & DYNAMIC) == 0)
     dynamic = false;
   else
-- 
2.40.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v4 4/7] ld: Add simple tests for -z nosectionheader
  2023-06-06 17:58 [PATCH v4 0/7] ELF: Strip section header in ELF objects H.J. Lu
                   ` (2 preceding siblings ...)
  2023-06-06 17:58 ` [PATCH v4 3/7] bfd: Improve nm and objdump " H.J. Lu
@ 2023-06-06 17:58 ` H.J. Lu
  2023-06-06 17:58 ` [PATCH v4 5/7] binutils: Add a --strip-section-headers test H.J. Lu
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 17+ messages in thread
From: H.J. Lu @ 2023-06-06 17:58 UTC (permalink / raw)
  To: binutils; +Cc: Alan Modra, Florian Weimer, Kaylee Blake

From: Kaylee Blake <klkblake@gmail.com>

2020-06-06  Kaylee Blake  <klkblake@gmail.com>
	    H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/25617
	* testsuite/ld-elf/nosectionheader-1.d: New file.
	* testsuite/ld-elf/nosectionheader-2.d: Likewise.
---
 ld/testsuite/ld-elf/nosectionheader-1.d | 14 ++++++++++++++
 ld/testsuite/ld-elf/nosectionheader-2.d |  4 ++++
 2 files changed, 18 insertions(+)
 create mode 100644 ld/testsuite/ld-elf/nosectionheader-1.d
 create mode 100644 ld/testsuite/ld-elf/nosectionheader-2.d

diff --git a/ld/testsuite/ld-elf/nosectionheader-1.d b/ld/testsuite/ld-elf/nosectionheader-1.d
new file mode 100644
index 00000000000..cbaea669b9a
--- /dev/null
+++ b/ld/testsuite/ld-elf/nosectionheader-1.d
@@ -0,0 +1,14 @@
+#source: start.s
+#ld: -z nosectionheader
+#readelf: -h -S
+#xfail: [uses_genelf]
+# These targets don't support -z.
+
+#...
+  Start of section headers:[ \t]+0 \(bytes into file\)
+#...
+  Size of section headers:[ \t]+0 \(bytes\)
+  Number of section headers:[ \t]+0
+  Section header string table index:[ \t]+0
+
+There are no sections in this file.
diff --git a/ld/testsuite/ld-elf/nosectionheader-2.d b/ld/testsuite/ld-elf/nosectionheader-2.d
new file mode 100644
index 00000000000..38c344ad697
--- /dev/null
+++ b/ld/testsuite/ld-elf/nosectionheader-2.d
@@ -0,0 +1,4 @@
+#source: start.s
+#ld: -r -z nosectionheader
+#error:  -r and -z nosectionheader may not be used together
+#xfail: [uses_genelf]
-- 
2.40.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v4 5/7] binutils: Add a --strip-section-headers test
  2023-06-06 17:58 [PATCH v4 0/7] ELF: Strip section header in ELF objects H.J. Lu
                   ` (3 preceding siblings ...)
  2023-06-06 17:58 ` [PATCH v4 4/7] ld: Add simple tests for -z nosectionheader H.J. Lu
@ 2023-06-06 17:58 ` H.J. Lu
  2023-06-06 17:58 ` [PATCH v4 6/7] ld: Add tests for -z nosectionheader and --strip-section-headers H.J. Lu
  2023-06-06 17:58 ` [PATCH v4 7/7] ld: Add -z nosectionheader test to bootstrap.exp H.J. Lu
  6 siblings, 0 replies; 17+ messages in thread
From: H.J. Lu @ 2023-06-06 17:58 UTC (permalink / raw)
  To: binutils; +Cc: Alan Modra, Florian Weimer, Kaylee Blake

	PR ld/25617
	* testsuite/binutils-all/objcopy.exp: Run strip-section-headers-1.
	* testsuite/binutils-all/strip-section-headers-1.d: New file.
---
 binutils/testsuite/binutils-all/objcopy.exp               | 5 +++++
 binutils/testsuite/binutils-all/strip-section-headers-1.d | 5 +++++
 2 files changed, 10 insertions(+)
 create mode 100644 binutils/testsuite/binutils-all/strip-section-headers-1.d

diff --git a/binutils/testsuite/binutils-all/objcopy.exp b/binutils/testsuite/binutils-all/objcopy.exp
index f6d4d1b839e..c70a26ca42e 100644
--- a/binutils/testsuite/binutils-all/objcopy.exp
+++ b/binutils/testsuite/binutils-all/objcopy.exp
@@ -1357,6 +1357,11 @@ if [is_elf_format] {
         verbose [file rootname $t]
         run_dump_test [file rootname $t]
     }
+
+    # Test --strip-section-headers
+    run_dump_test "strip-section-headers-1" [list \
+			  [list source strip-15${reloc_format}.s] \
+			  [list as "${elf64} --defsym RELOC=${reloc}"]]
 }
 run_dump_test "localize-hidden-2"
 
diff --git a/binutils/testsuite/binutils-all/strip-section-headers-1.d b/binutils/testsuite/binutils-all/strip-section-headers-1.d
new file mode 100644
index 00000000000..dc249bba779
--- /dev/null
+++ b/binutils/testsuite/binutils-all/strip-section-headers-1.d
@@ -0,0 +1,5 @@
+#PROG: strip
+#strip: -g --strip-section-headers
+#readelf: -S
+
+There are no sections in this file.
-- 
2.40.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v4 6/7] ld: Add tests for -z nosectionheader and --strip-section-headers
  2023-06-06 17:58 [PATCH v4 0/7] ELF: Strip section header in ELF objects H.J. Lu
                   ` (4 preceding siblings ...)
  2023-06-06 17:58 ` [PATCH v4 5/7] binutils: Add a --strip-section-headers test H.J. Lu
@ 2023-06-06 17:58 ` H.J. Lu
  2023-06-29 20:56   ` H.J. Lu
  2023-06-06 17:58 ` [PATCH v4 7/7] ld: Add -z nosectionheader test to bootstrap.exp H.J. Lu
  6 siblings, 1 reply; 17+ messages in thread
From: H.J. Lu @ 2023-06-06 17:58 UTC (permalink / raw)
  To: binutils; +Cc: Alan Modra, Florian Weimer, Kaylee Blake

Add tests to verify that the linker option, -z nosectionheader and
objcopy and strip option, --strip-section-headers, work correctly as well
as linker issues an error when dynamic symbol table from PT_DYNAMIC
segment is used.

	PR ld/25617
	* testsuite/ld-elf/hash-2.d: New file.
	* testsuite/ld-elf/no-section-header.exp: Likewise.
	* testsuite/ld-elf/pr25617-1-no-sec-hdr.nd: Likewise.
	* testsuite/ld-elf/pr25617-1-no-sec-hdr.rd: Likewise.
	* testsuite/ld-elf/pr25617-1-static-no-sec-hdr.rd: Likewise.
	* testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd: Likewise.
	* testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd: Likewise.
	* testsuite/ld-elf/pr25617-1a-sec-hdr.rd: Likewise.
	* testsuite/ld-elf/pr25617-1a.c: Likewise.
	* testsuite/ld-elf/pr25617-1b.c: Likewise.
	* testsuite/ld-elf/start-noheader.rd: Likewise.
	* testsuite/ld-elf/start-shared-noheader-gnu.rd: Likewise.
	* testsuite/ld-elf/start-shared-noheader-sysv.rd: Likewise.
	* testsuite/ld-elf/start-shared-noheader.nd: Likewise.
---
 ld/testsuite/ld-elf/hash-2.d                  |  11 +
 ld/testsuite/ld-elf/no-section-header.exp     | 371 ++++++++++++++++++
 ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.nd   |   3 +
 ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.rd   |  20 +
 .../ld-elf/pr25617-1-static-no-sec-hdr.rd     |  12 +
 ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd  |   3 +
 ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd  |  20 +
 ld/testsuite/ld-elf/pr25617-1a-sec-hdr.rd     |  19 +
 ld/testsuite/ld-elf/pr25617-1a.c              |  11 +
 ld/testsuite/ld-elf/pr25617-1b.c              |  15 +
 ld/testsuite/ld-elf/start-noheader.rd         |  11 +
 .../ld-elf/start-shared-noheader-gnu.rd       |  26 ++
 .../ld-elf/start-shared-noheader-sysv.rd      |  26 ++
 ld/testsuite/ld-elf/start-shared-noheader.nd  |  11 +
 14 files changed, 559 insertions(+)
 create mode 100644 ld/testsuite/ld-elf/hash-2.d
 create mode 100644 ld/testsuite/ld-elf/no-section-header.exp
 create mode 100644 ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.nd
 create mode 100644 ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.rd
 create mode 100644 ld/testsuite/ld-elf/pr25617-1-static-no-sec-hdr.rd
 create mode 100644 ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd
 create mode 100644 ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd
 create mode 100644 ld/testsuite/ld-elf/pr25617-1a-sec-hdr.rd
 create mode 100644 ld/testsuite/ld-elf/pr25617-1a.c
 create mode 100644 ld/testsuite/ld-elf/pr25617-1b.c
 create mode 100644 ld/testsuite/ld-elf/start-noheader.rd
 create mode 100644 ld/testsuite/ld-elf/start-shared-noheader-gnu.rd
 create mode 100644 ld/testsuite/ld-elf/start-shared-noheader-sysv.rd
 create mode 100644 ld/testsuite/ld-elf/start-shared-noheader.nd

diff --git a/ld/testsuite/ld-elf/hash-2.d b/ld/testsuite/ld-elf/hash-2.d
new file mode 100644
index 00000000000..91320d3d6ab
--- /dev/null
+++ b/ld/testsuite/ld-elf/hash-2.d
@@ -0,0 +1,11 @@
+#source: start.s
+#readelf: -d -s
+#ld: -shared --hash-style=gnu -z nosectionheader
+#target: *-*-linux* *-*-gnu* arm*-*-uclinuxfdpiceabi
+#xfail: ![check_shared_lib_support] mips*-*-*
+# MIPS uses a different style of GNU hash due to psABI restrictions
+# on dynsym table ordering.
+
+#...
+ +0x[0-9a-z]+ +\(GNU_HASH\) +0x[0-9a-z]+
+#pass
diff --git a/ld/testsuite/ld-elf/no-section-header.exp b/ld/testsuite/ld-elf/no-section-header.exp
new file mode 100644
index 00000000000..fe0a57554b3
--- /dev/null
+++ b/ld/testsuite/ld-elf/no-section-header.exp
@@ -0,0 +1,371 @@
+# Expect script for -z nosectionheader and --strip-section-headers tests
+# Copyright (C) 2023 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+# Written by H.J. Lu (hongjiu.lu@intel.com)
+#
+
+# Make sure that binutils can correctly handle ld output in ELF.
+
+if { ![istarget *-*-linux*] } {
+    return
+}
+
+proc binutils_test { prog_name ld_options test readelf_expected nm_expected} {
+    global as
+    global ld
+    global READELF
+    global NM
+    global objcopy
+    global strip
+    global srcdir
+    global subdir
+    global link_output
+
+    eval set prog \$$prog_name
+
+    set test_name "$prog_name --strip-section-headers $ld_options ($test)"
+
+    if { ![ld_assemble $as $srcdir/$subdir/$test.s tmpdir/$test.o ] } {
+	unresolved "$test_name"
+	return
+    }
+
+    append ld_options " -z separate-code -z stack-size=0"
+    if { ![ld_link $ld tmpdir/$test "$ld_options tmpdir/$test.o"] } {
+	if { [string match "*not supported*" $link_output]
+	     || [string match "*unrecognized option*" $link_output]
+	     || [string match "*-z .* ignored*" $link_output] } {
+	    unsupported "$ld_options is not supported by this target"
+	} else {
+	    unresolved "$test_name"
+	}
+	return
+    }
+
+    send_log "$prog --strip-section-headers tmpdir/$test\n"
+    set got [remote_exec host "$prog --strip-section-headers tmpdir/$test"]
+    if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
+	send_log "$got\n"
+	fail "$test_name"
+	return
+    }
+
+    send_log "$READELF -lSDs --wide tmpdir/$test > tmpdir/$test.out\n"
+    set got [remote_exec host "$READELF -lSDs --wide tmpdir/$test" "" "/dev/null" "tmpdir/$test.out"]
+    if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
+	send_log "$got\n"
+	unresolved "$test_name"
+	return
+    }
+
+    if { [regexp_diff "tmpdir/$test.out" "$srcdir/$subdir/$readelf_expected"] } then {
+	fail "$test_name"
+	return
+    }
+
+    if { [string match "*-shared *" $ld_options] } {
+	send_log "$NM -D tmpdir/$test > tmpdir/$test.out\n"
+	set got [remote_exec host "$NM -D tmpdir/$test" "" "/dev/null" "tmpdir/$test.out"]
+	if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
+	    send_log "$got\n"
+	    unresolved "$test_name"
+	    return
+	}
+
+	if { [regexp_diff "tmpdir/$test.out" "$srcdir/$subdir/$nm_expected"] } then {
+	    fail "$test_name"
+	    return
+	}
+    }
+
+    pass "$test_name"
+}
+
+if { [istarget "mips*-*-*"] } {
+    set gnu_hash_style "sysv"
+} else {
+    set gnu_hash_style "gnu"
+}
+
+binutils_test objcopy "--hash-style=both" start start-noheader.rd \
+	start-noheader.nd
+binutils_test objcopy "--hash-style=gnu" start start-noheader.rd \
+	start-noheader.nd
+binutils_test objcopy "--hash-style=sysv" start start-noheader.rd \
+	start-noheader.nd
+binutils_test objcopy "--hash-style=both -shared" start \
+	start-shared-noheader-$gnu_hash_style.rd start-shared-noheader.nd
+binutils_test objcopy "--hash-style=gnu -shared" start \
+	start-shared-noheader-$gnu_hash_style.rd start-shared-noheader.nd
+binutils_test objcopy "--hash-style=sysv -shared" start \
+	start-shared-noheader-sysv.rd start-shared-noheader.nd
+binutils_test strip "--hash-style=both" start start-noheader.rd \
+	start-noheader.nd
+binutils_test strip "--hash-style=gnu" start start-noheader.rd \
+	start-noheader.nd
+binutils_test strip "--hash-style=sysv" start start-noheader.rd \
+	start-noheader.nd
+binutils_test strip "--hash-style=both -shared" start \
+	start-shared-noheader-$gnu_hash_style.rd start-shared-noheader.nd
+binutils_test strip "--hash-style=gnu -shared" start \
+	start-shared-noheader-$gnu_hash_style.rd start-shared-noheader.nd
+binutils_test strip "--hash-style=sysv -shared" start \
+	start-shared-noheader-sysv.rd start-shared-noheader.nd
+
+# Skip non-native targets or -shared is not supported.
+if { ![isnative] || ![check_shared_lib_support] } {
+    return
+}
+
+proc binutils_run_test { prog } {
+    global CC
+    global gcc_B_opt
+    global READELF
+    global NM
+    global objcopy
+    global strip
+    global srcdir
+    global subdir
+    # Add $NOPIE_CFLAGS and $NOPIE_LDFLAGS if non-PIE is required.
+    global NOPIE_CFLAGS NOPIE_LDFLAGS
+
+    set sec_hdr "sec-hdr"
+    if { "$prog" == "" } {
+	set prog_name none
+    } else {
+	set prog_name $prog
+	set ld_options ""
+	switch -- $prog {
+	    objcopy
+	        { set prog $objcopy }
+	    strip
+	        { set prog $strip }
+	    default
+		{
+		    fail "Build pr25617-1a-no-sec-hdr.so ($prog_name)"
+		    break
+		}
+	}
+    }
+
+    run_cc_link_tests [list \
+	[list \
+	    "Build pr25617-1a-no-sec-hdr.so ($prog_name)" \
+	    "-shared -Wl,-z,separate-code,--hash-style=sysv" \
+	    "-fPIC" \
+	    {pr25617-1a.c} \
+	    [list \
+		[list "readelf" "-lWSDs" "pr25617-1a-$sec_hdr.rd"] \
+		[list "nm" "-D" "pr25617-1a-no-sec-hdr.nd"] \
+	    ]\
+	    "pr25617-1a-no-sec-hdr.so" \
+	] \
+	[list \
+	    "Build pr25617-1a-now-no-sec-hdr.so ($prog_name)" \
+	    "-shared -Wl,-z,separate-code,-z,now,--hash-style=gnu" \
+	    "-fPIC" \
+	    {pr25617-1a.c} \
+	    [list \
+		[list "readelf" "-lWSDs" "pr25617-1a-$sec_hdr.rd"] \
+		[list "nm" "-D" "pr25617-1a-no-sec-hdr.nd"] \
+	    ]\
+	    "pr25617-1a-now-no-sec-hdr.so" \
+	] \
+	[list \
+	    "Build pr25617-1 (-z nosectionheader, $prog_name)" \
+	    "$NOPIE_LDFLAGS -Wl,-z,separate-code,--no-as-needed \
+	     -Wl,--hash-style=sysv -Wl,-z,nosectionheader \
+	     tmpdir/pr25617-1a-no-sec-hdr.so" \
+	    "$NOPIE_CFLAGS" \
+	    {pr25617-1b.c} \
+	    {{readelf -lWSDs pr25617-1-no-sec-hdr.rd} \
+	     {nm -D pr25617-1-no-sec-hdr.nd}} \
+	    "pr25617-1-no-sec-hdr" \
+	] \
+	[list \
+	    "Build pr25617-1 (PIE, -z nosectionheader, $prog_name)" \
+	    "-pie -Wl,-z,separate-code,--no-as-needed,--hash-style=gnu \
+	     -Wl,-z,nosectionheader tmpdir/pr25617-1a-now-no-sec-hdr.so" \
+	    "-fPIE" \
+	    {pr25617-1b.c} \
+	    {{readelf -lWSDs pr25617-1-no-sec-hdr.rd} \
+	     {nm -D pr25617-1-no-sec-hdr.nd}} \
+	    "pr25617-1-pie-no-sec-hdr" \
+	] \
+	[list \
+	    "Build pr25617-1 (static, -z nosectionheader, $prog_name)" \
+	    "-static -Wl,-z,separate-code -Wl,-z,nosectionheader" \
+	    "" \
+	    {pr25617-1a.c pr25617-1b.c} \
+	    {{readelf -lSWDs pr25617-1-static-no-sec-hdr.rd}} \
+	    "pr25617-1-static-no-sec-hdr" \
+	] \
+    ]
+
+    run_ld_link_exec_tests [list \
+	[list \
+	    "Run pr25617-1 (-z nosectionheader, $prog_name)" \
+	    "$NOPIE_LDFLAGS -Wl,-z,separate-code,--no-as-needed \
+	     -Wl,--hash-style=sysv -Wl,-z,nosectionheader \
+	     tmpdir/pr25617-1a-no-sec-hdr.so" \
+	    "" \
+	    {pr25617-1b.c} \
+	    "pr25617-1-no-sec-hdr" \
+	    "pass.out" \
+	    "$NOPIE_CFLAGS" \
+	] \
+	[list \
+	    "Run pr25617-1 (PIE, -z nosectionheader, $prog_name)" \
+	    "-pie -Wl,-z,separate-code,--no-as-needed,--hash-style=gnu \
+	     -Wl,-z,nosectionheader tmpdir/pr25617-1a-now-no-sec-hdr.so" \
+	    "" \
+	    {pr25617-1b.c} \
+	    "pr25617-1-pie-no-sec-hdr" \
+	    "pass.out" \
+	    "-fPIE" \
+	] \
+	[list \
+	    "Run pr25617-1 (static, -z nosectionheader, $prog_name)" \
+	    "-static -Wl,-z,separate-code -Wl,-z,nosectionheader" \
+	    "" \
+	    {pr25617-1a.c pr25617-1b.c} \
+	    "pr25617-1-static-no-sec-hdr" \
+	    "pass.out" \
+	] \
+    ]
+
+    if { "$prog_name" != "none" } {
+	send_log "$prog --strip-section-headers tmpdir/pr25617-1a-no-sec-hdr.so\n"
+	set got [remote_exec host "$prog --strip-section-headers tmpdir/pr25617-1a-no-sec-hdr.so"]
+	if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
+	    send_log "$got\n"
+	    fail "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
+	    return
+	}
+
+	send_log "$READELF -lWSDs tmpdir/pr25617-1a-no-sec-hdr.so > tmpdir/dump.out\n"
+	set got [remote_exec host "$READELF -lWSDs tmpdir/pr25617-1a-no-sec-hdr.so" "" "/dev/null" "tmpdir/dump.out"]
+	if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
+	    send_log "$got\n"
+	    unresolved "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
+	    return
+	}
+
+	if { [regexp_diff "tmpdir/dump.out" "$srcdir/$subdir/pr25617-1a-no-sec-hdr.rd"] } then {
+	    unresolved "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
+	    return
+	}
+
+	send_log "$NM -D tmpdir/pr25617-1a-no-sec-hdr.so > tmpdir/dump.out\n"
+	set got [remote_exec host "$NM -D tmpdir/pr25617-1a-no-sec-hdr.so" "" "/dev/null" "tmpdir/dump.out"]
+	if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
+	    send_log "$got\n"
+	    unresolved "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
+	    return
+	}
+
+	if { [regexp_diff "tmpdir/dump.out" "$srcdir/$subdir/pr25617-1a-no-sec-hdr.nd"] } then {
+	    unresolved "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
+	    return
+	}
+
+	send_log "tmpdir/pr25617-1-no-sec-hdr > tmpdir/pr25617-1.out\n"
+	catch "exec tmpdir/pr25617-1-no-sec-hdr > tmpdir/pr25617-1.out" got
+	if ![string match "" $got] then {
+	    send_log "$got\n"
+	    unresolved "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
+	    return
+	}
+
+	send_log "diff tmpdir/pr25617-1.out $srcdir/$subdir/pass.out\n"
+	catch "exec diff tmpdir/pr25617-1.out $srcdir/$subdir/pass.out" got
+	if ![string match "" $got] then {
+	    send_log "$got\n"
+	    fail "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
+	    return
+	}
+
+	pass "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
+
+	send_log "$prog --strip-section-headers tmpdir/pr25617-1a-now-no-sec-hdr.so\n"
+	set got [remote_exec host "$prog --strip-section-headers tmpdir/pr25617-1a-now-no-sec-hdr.so"]
+	if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
+	    send_log "$got\n"
+	    fail "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
+	    return
+	}
+
+	send_log "$READELF -lWSDs tmpdir/pr25617-1a-now-no-sec-hdr.so > tmpdir/dump.out\n"
+	set got [remote_exec host "$READELF -lWSDs tmpdir/pr25617-1a-now-no-sec-hdr.so" "" "/dev/null" "tmpdir/dump.out"]
+	if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
+	    send_log "$got\n"
+	    unresolved "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
+	    return
+	}
+
+	if { [regexp_diff "tmpdir/dump.out" "$srcdir/$subdir/pr25617-1a-no-sec-hdr.rd"] } then {
+	    unresolved "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
+	    return
+	}
+
+	send_log "$NM -D tmpdir/pr25617-1a-now-no-sec-hdr.so > tmpdir/dump.out\n"
+	set got [remote_exec host "$NM -D tmpdir/pr25617-1a-now-no-sec-hdr.so" "" "/dev/null" "tmpdir/dump.out"]
+	if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
+	    send_log "$got\n"
+	    unresolved "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
+	    return
+	}
+
+	if { [regexp_diff "tmpdir/dump.out" "$srcdir/$subdir/pr25617-1a-no-sec-hdr.nd"] } then {
+	    unresolved "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
+	    return
+	}
+
+	send_log "tmpdir/pr25617-1-pie-no-sec-hdr > tmpdir/pr25617-1-pie.out\n"
+	catch "exec tmpdir/pr25617-1-pie-no-sec-hdr > tmpdir/pr25617-1-pie.out" got
+	if ![string match "" $got] then {
+	    send_log "$got\n"
+	    unresolved "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
+	    return
+	}
+
+	send_log "diff tmpdir/pr25617-1-pie.out $srcdir/$subdir/pass.out\n"
+	catch "exec diff tmpdir/pr25617-1-pie.out $srcdir/$subdir/pass.out" got
+	if ![string match "" $got] then {
+	    send_log "$got\n"
+	    fail "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
+	    return
+	}
+
+	send_log "$CC $gcc_B_opt -o tmpdir/pr25617-1 tmpdir/pr25617-1b.o tmpdir/pr25617-1a-now-no-sec-hdr.so\n"
+	catch "exec $CC $gcc_B_opt -o tmpdir/pr25617-1 tmpdir/pr25617-1b.o tmpdir/pr25617-1a-now-no-sec-hdr.so" got
+	if ![string match "*pr25617-1a-now-no-sec-hdr.so*file in wrong format*" $got] then {
+	    send_log "$got\n"
+	    fail "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
+	    return
+	}
+
+	pass "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
+     }
+}
+
+binutils_run_test ""
+binutils_run_test objcopy
+binutils_run_test strip
diff --git a/ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.nd b/ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.nd
new file mode 100644
index 00000000000..6a96f5b55a3
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.nd
@@ -0,0 +1,3 @@
+#...
+[a-f0-9 ]+ [DU] _?protected
+ + U _?test
diff --git a/ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.rd b/ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.rd
new file mode 100644
index 00000000000..be49dea32db
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.rd
@@ -0,0 +1,20 @@
+#readelf: -lWSDs
+
+There are no sections in this file.
+
+#...
+Program Headers:
+  Type +Offset +VirtAddr.*
+# On MIPS, the first segment is for .reginfo.
+#...
+  LOAD .*
+#...
+  DYNAMIC .*
+#...
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +FUNC +GLOBAL +DEFAULT +UND +__libc_start_main(@.*|)
+#...
+ +[0-9]+: +[a-f0-9]+ +0+ +FUNC +GLOBAL +DEFAULT +UND +_?test
+#pass
diff --git a/ld/testsuite/ld-elf/pr25617-1-static-no-sec-hdr.rd b/ld/testsuite/ld-elf/pr25617-1-static-no-sec-hdr.rd
new file mode 100644
index 00000000000..92b1dc9ead9
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25617-1-static-no-sec-hdr.rd
@@ -0,0 +1,12 @@
+#readelf: -lWSDs
+
+There are no sections in this file.
+
+#...
+Program Headers:
+  Type +Offset +VirtAddr.*
+# On MIPS, the first segment is for .reginfo.
+#...
+  LOAD .*
+#...
+Dynamic symbol information is not available for displaying symbols\.
diff --git a/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd b/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd
new file mode 100644
index 00000000000..2813ffc6652
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd
@@ -0,0 +1,3 @@
+#...
+ + U _?puts(@.*|)
+[0-9a-z]+ T _?test
diff --git a/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd b/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd
new file mode 100644
index 00000000000..f7a4eec7362
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd
@@ -0,0 +1,20 @@
+#readelf: -lWSDs
+
+There are no sections in this file.
+
+#...
+Program Headers:
+  Type +Offset +VirtAddr.*
+# On MIPS, the first segment is for .reginfo.
+#...
+  LOAD .*
+#...
+  DYNAMIC .*
+#...
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +FUNC +GLOBAL +DEFAULT +UND +_?puts(@.*|)
+#...
+ +[0-9]+: +[a-f0-9]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +[0-9]+ +_?test
+#pass
diff --git a/ld/testsuite/ld-elf/pr25617-1a-sec-hdr.rd b/ld/testsuite/ld-elf/pr25617-1a-sec-hdr.rd
new file mode 100644
index 00000000000..9ccf0565af6
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25617-1a-sec-hdr.rd
@@ -0,0 +1,19 @@
+#readelf: -lWSDs
+
+There are [0-9]+ section headers, starting at offset 0x[a-f0-9]+:
+#...
+Program Headers:
+  Type +Offset +VirtAddr.*
+# On MIPS, the first segment is for .reginfo.
+#...
+  LOAD .*
+#...
+  DYNAMIC .*
+#...
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +FUNC +GLOBAL +DEFAULT +UND +_?puts(@.*|)
+#...
+ +[0-9]+: +[a-f0-9]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +[0-9]+ +_?test
+#pass
diff --git a/ld/testsuite/ld-elf/pr25617-1a.c b/ld/testsuite/ld-elf/pr25617-1a.c
new file mode 100644
index 00000000000..f707f266fe2
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25617-1a.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+int protected = 42;
+extern int *get_protected_ptr (void);
+
+void
+test()
+{
+  if (&protected == get_protected_ptr ())
+    printf ("PASS\n");
+}
diff --git a/ld/testsuite/ld-elf/pr25617-1b.c b/ld/testsuite/ld-elf/pr25617-1b.c
new file mode 100644
index 00000000000..1fd6ef45d79
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25617-1b.c
@@ -0,0 +1,15 @@
+void test(void);
+
+extern int protected;
+
+int *
+get_protected_ptr (void)
+{
+  return &protected;
+}
+
+int main()
+{
+  test();
+  return 0;
+}
diff --git a/ld/testsuite/ld-elf/start-noheader.rd b/ld/testsuite/ld-elf/start-noheader.rd
new file mode 100644
index 00000000000..2479e340871
--- /dev/null
+++ b/ld/testsuite/ld-elf/start-noheader.rd
@@ -0,0 +1,11 @@
+#readelf: -SlDs --wide
+
+There are no sections in this file.
+
+#...
+Program Headers:
+  Type +Offset +VirtAddr.*
+# On MIPS, the first segment is for .reginfo.
+#...
+  LOAD .*
+#pass
diff --git a/ld/testsuite/ld-elf/start-shared-noheader-gnu.rd b/ld/testsuite/ld-elf/start-shared-noheader-gnu.rd
new file mode 100644
index 00000000000..20bc30cad4c
--- /dev/null
+++ b/ld/testsuite/ld-elf/start-shared-noheader-gnu.rd
@@ -0,0 +1,26 @@
+#readelf: -SlDs --wide
+
+There are no sections in this file.
+
+#...
+Program Headers:
+  Type +Offset +VirtAddr.*
+# On MIPS, the first segment is for .reginfo.
+#...
+  LOAD .*
+#...
+  DYNAMIC .*
+#...
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +_start
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +main
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +start
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +_main
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +__start
+#pass
diff --git a/ld/testsuite/ld-elf/start-shared-noheader-sysv.rd b/ld/testsuite/ld-elf/start-shared-noheader-sysv.rd
new file mode 100644
index 00000000000..d8f02497e58
--- /dev/null
+++ b/ld/testsuite/ld-elf/start-shared-noheader-sysv.rd
@@ -0,0 +1,26 @@
+#readelf: -SlDs --wide
+
+There are no sections in this file.
+
+#...
+Program Headers:
+  Type +Offset +VirtAddr.*
+# On MIPS, the first segment is for .reginfo.
+#...
+  LOAD .*
+#...
+  DYNAMIC .*
+#...
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +__start
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +_start
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +main
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +start
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +_main
+#pass
diff --git a/ld/testsuite/ld-elf/start-shared-noheader.nd b/ld/testsuite/ld-elf/start-shared-noheader.nd
new file mode 100644
index 00000000000..6ec6cdf8af9
--- /dev/null
+++ b/ld/testsuite/ld-elf/start-shared-noheader.nd
@@ -0,0 +1,11 @@
+#...
+[0-9a-z]+ A __start
+#...
+[0-9a-z]+ A _main
+#...
+[0-9a-z]+ A _start
+#...
+[0-9a-z]+ A main
+#...
+[0-9a-z]+ A start
+#pass
-- 
2.40.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v4 7/7] ld: Add -z nosectionheader test to bootstrap.exp
  2023-06-06 17:58 [PATCH v4 0/7] ELF: Strip section header in ELF objects H.J. Lu
                   ` (5 preceding siblings ...)
  2023-06-06 17:58 ` [PATCH v4 6/7] ld: Add tests for -z nosectionheader and --strip-section-headers H.J. Lu
@ 2023-06-06 17:58 ` H.J. Lu
  6 siblings, 0 replies; 17+ messages in thread
From: H.J. Lu @ 2023-06-06 17:58 UTC (permalink / raw)
  To: binutils; +Cc: Alan Modra, Florian Weimer, Kaylee Blake

	PR ld/25617
	* testsuite/ld-bootstrap/bootstrap.exp: Add -z nosectionheader
	test.
---
 ld/testsuite/ld-bootstrap/bootstrap.exp | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/ld/testsuite/ld-bootstrap/bootstrap.exp b/ld/testsuite/ld-bootstrap/bootstrap.exp
index b189a0c7098..7b70b9582c0 100644
--- a/ld/testsuite/ld-bootstrap/bootstrap.exp
+++ b/ld/testsuite/ld-bootstrap/bootstrap.exp
@@ -66,6 +66,9 @@ set test_flags {"" "strip" "--static" "-Wl,--traditional-format"
 if { [istarget "powerpc-*-*"] } {
     lappend test_flags "-Wl,--ppc476-workaround"
 }
+if { [is_elf_format] && ![is_bad_symtab] } {
+    lappend test_flags "-Wl,-z,nosectionheader"
+}
 
 set gcc_B_opt_save $gcc_B_opt
 
@@ -94,9 +97,12 @@ foreach flags $test_flags {
 	set testname "bootstrap"
     }}
 
-    # --static is meaningless and --relax is incompatible with -r.
+    # --static is meaningless.  --relax and -z nosectionheader are
+    # incompatible with -r.
     regsub -- "-Wl," $flags "" partial_flags
-    if { "$partial_flags" == "--static" || "$partial_flags" == "--relax" } {
+    if { "$partial_flags" == "--static" \
+         || "$partial_flags" == "--relax" \
+	 || [string match "*nosectionheader*" "$partial_flags"] } {
 	set partial_flags ""
     }
 
-- 
2.40.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 6/7] ld: Add tests for -z nosectionheader and --strip-section-headers
  2023-06-06 17:58 ` [PATCH v4 6/7] ld: Add tests for -z nosectionheader and --strip-section-headers H.J. Lu
@ 2023-06-29 20:56   ` H.J. Lu
  2023-07-06  1:27     ` Alan Modra
  0 siblings, 1 reply; 17+ messages in thread
From: H.J. Lu @ 2023-06-29 20:56 UTC (permalink / raw)
  To: binutils; +Cc: Alan Modra

On Tue, Jun 6, 2023 at 10:58 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> Add tests to verify that the linker option, -z nosectionheader and
> objcopy and strip option, --strip-section-headers, work correctly as well
> as linker issues an error when dynamic symbol table from PT_DYNAMIC
> segment is used.
>
>         PR ld/25617
>         * testsuite/ld-elf/hash-2.d: New file.
>         * testsuite/ld-elf/no-section-header.exp: Likewise.
>         * testsuite/ld-elf/pr25617-1-no-sec-hdr.nd: Likewise.
>         * testsuite/ld-elf/pr25617-1-no-sec-hdr.rd: Likewise.
>         * testsuite/ld-elf/pr25617-1-static-no-sec-hdr.rd: Likewise.
>         * testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd: Likewise.
>         * testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd: Likewise.
>         * testsuite/ld-elf/pr25617-1a-sec-hdr.rd: Likewise.
>         * testsuite/ld-elf/pr25617-1a.c: Likewise.
>         * testsuite/ld-elf/pr25617-1b.c: Likewise.
>         * testsuite/ld-elf/start-noheader.rd: Likewise.
>         * testsuite/ld-elf/start-shared-noheader-gnu.rd: Likewise.
>         * testsuite/ld-elf/start-shared-noheader-sysv.rd: Likewise.
>         * testsuite/ld-elf/start-shared-noheader.nd: Likewise.
> ---
>  ld/testsuite/ld-elf/hash-2.d                  |  11 +
>  ld/testsuite/ld-elf/no-section-header.exp     | 371 ++++++++++++++++++
>  ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.nd   |   3 +
>  ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.rd   |  20 +
>  .../ld-elf/pr25617-1-static-no-sec-hdr.rd     |  12 +
>  ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd  |   3 +
>  ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd  |  20 +
>  ld/testsuite/ld-elf/pr25617-1a-sec-hdr.rd     |  19 +
>  ld/testsuite/ld-elf/pr25617-1a.c              |  11 +
>  ld/testsuite/ld-elf/pr25617-1b.c              |  15 +
>  ld/testsuite/ld-elf/start-noheader.rd         |  11 +
>  .../ld-elf/start-shared-noheader-gnu.rd       |  26 ++
>  .../ld-elf/start-shared-noheader-sysv.rd      |  26 ++
>  ld/testsuite/ld-elf/start-shared-noheader.nd  |  11 +
>  14 files changed, 559 insertions(+)
>  create mode 100644 ld/testsuite/ld-elf/hash-2.d
>  create mode 100644 ld/testsuite/ld-elf/no-section-header.exp
>  create mode 100644 ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.nd
>  create mode 100644 ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.rd
>  create mode 100644 ld/testsuite/ld-elf/pr25617-1-static-no-sec-hdr.rd
>  create mode 100644 ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd
>  create mode 100644 ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd
>  create mode 100644 ld/testsuite/ld-elf/pr25617-1a-sec-hdr.rd
>  create mode 100644 ld/testsuite/ld-elf/pr25617-1a.c
>  create mode 100644 ld/testsuite/ld-elf/pr25617-1b.c
>  create mode 100644 ld/testsuite/ld-elf/start-noheader.rd
>  create mode 100644 ld/testsuite/ld-elf/start-shared-noheader-gnu.rd
>  create mode 100644 ld/testsuite/ld-elf/start-shared-noheader-sysv.rd
>  create mode 100644 ld/testsuite/ld-elf/start-shared-noheader.nd
>
> diff --git a/ld/testsuite/ld-elf/hash-2.d b/ld/testsuite/ld-elf/hash-2.d
> new file mode 100644
> index 00000000000..91320d3d6ab
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/hash-2.d
> @@ -0,0 +1,11 @@
> +#source: start.s
> +#readelf: -d -s
> +#ld: -shared --hash-style=gnu -z nosectionheader
> +#target: *-*-linux* *-*-gnu* arm*-*-uclinuxfdpiceabi
> +#xfail: ![check_shared_lib_support] mips*-*-*
> +# MIPS uses a different style of GNU hash due to psABI restrictions
> +# on dynsym table ordering.
> +
> +#...
> + +0x[0-9a-z]+ +\(GNU_HASH\) +0x[0-9a-z]+
> +#pass
> diff --git a/ld/testsuite/ld-elf/no-section-header.exp b/ld/testsuite/ld-elf/no-section-header.exp
> new file mode 100644
> index 00000000000..fe0a57554b3
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/no-section-header.exp
> @@ -0,0 +1,371 @@
> +# Expect script for -z nosectionheader and --strip-section-headers tests
> +# Copyright (C) 2023 Free Software Foundation, Inc.
> +#
> +# This file is part of the GNU Binutils.
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
> +# MA 02110-1301, USA.
> +#
> +# Written by H.J. Lu (hongjiu.lu@intel.com)
> +#
> +
> +# Make sure that binutils can correctly handle ld output in ELF.
> +
> +if { ![istarget *-*-linux*] } {
> +    return
> +}
> +
> +proc binutils_test { prog_name ld_options test readelf_expected nm_expected} {
> +    global as
> +    global ld
> +    global READELF
> +    global NM
> +    global objcopy
> +    global strip
> +    global srcdir
> +    global subdir
> +    global link_output
> +
> +    eval set prog \$$prog_name
> +
> +    set test_name "$prog_name --strip-section-headers $ld_options ($test)"
> +
> +    if { ![ld_assemble $as $srcdir/$subdir/$test.s tmpdir/$test.o ] } {
> +       unresolved "$test_name"
> +       return
> +    }
> +
> +    append ld_options " -z separate-code -z stack-size=0"
> +    if { ![ld_link $ld tmpdir/$test "$ld_options tmpdir/$test.o"] } {
> +       if { [string match "*not supported*" $link_output]
> +            || [string match "*unrecognized option*" $link_output]
> +            || [string match "*-z .* ignored*" $link_output] } {
> +           unsupported "$ld_options is not supported by this target"
> +       } else {
> +           unresolved "$test_name"
> +       }
> +       return
> +    }
> +
> +    send_log "$prog --strip-section-headers tmpdir/$test\n"
> +    set got [remote_exec host "$prog --strip-section-headers tmpdir/$test"]
> +    if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
> +       send_log "$got\n"
> +       fail "$test_name"
> +       return
> +    }
> +
> +    send_log "$READELF -lSDs --wide tmpdir/$test > tmpdir/$test.out\n"
> +    set got [remote_exec host "$READELF -lSDs --wide tmpdir/$test" "" "/dev/null" "tmpdir/$test.out"]
> +    if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
> +       send_log "$got\n"
> +       unresolved "$test_name"
> +       return
> +    }
> +
> +    if { [regexp_diff "tmpdir/$test.out" "$srcdir/$subdir/$readelf_expected"] } then {
> +       fail "$test_name"
> +       return
> +    }
> +
> +    if { [string match "*-shared *" $ld_options] } {
> +       send_log "$NM -D tmpdir/$test > tmpdir/$test.out\n"
> +       set got [remote_exec host "$NM -D tmpdir/$test" "" "/dev/null" "tmpdir/$test.out"]
> +       if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
> +           send_log "$got\n"
> +           unresolved "$test_name"
> +           return
> +       }
> +
> +       if { [regexp_diff "tmpdir/$test.out" "$srcdir/$subdir/$nm_expected"] } then {
> +           fail "$test_name"
> +           return
> +       }
> +    }
> +
> +    pass "$test_name"
> +}
> +
> +if { [istarget "mips*-*-*"] } {
> +    set gnu_hash_style "sysv"
> +} else {
> +    set gnu_hash_style "gnu"
> +}
> +
> +binutils_test objcopy "--hash-style=both" start start-noheader.rd \
> +       start-noheader.nd
> +binutils_test objcopy "--hash-style=gnu" start start-noheader.rd \
> +       start-noheader.nd
> +binutils_test objcopy "--hash-style=sysv" start start-noheader.rd \
> +       start-noheader.nd
> +binutils_test objcopy "--hash-style=both -shared" start \
> +       start-shared-noheader-$gnu_hash_style.rd start-shared-noheader.nd
> +binutils_test objcopy "--hash-style=gnu -shared" start \
> +       start-shared-noheader-$gnu_hash_style.rd start-shared-noheader.nd
> +binutils_test objcopy "--hash-style=sysv -shared" start \
> +       start-shared-noheader-sysv.rd start-shared-noheader.nd
> +binutils_test strip "--hash-style=both" start start-noheader.rd \
> +       start-noheader.nd
> +binutils_test strip "--hash-style=gnu" start start-noheader.rd \
> +       start-noheader.nd
> +binutils_test strip "--hash-style=sysv" start start-noheader.rd \
> +       start-noheader.nd
> +binutils_test strip "--hash-style=both -shared" start \
> +       start-shared-noheader-$gnu_hash_style.rd start-shared-noheader.nd
> +binutils_test strip "--hash-style=gnu -shared" start \
> +       start-shared-noheader-$gnu_hash_style.rd start-shared-noheader.nd
> +binutils_test strip "--hash-style=sysv -shared" start \
> +       start-shared-noheader-sysv.rd start-shared-noheader.nd
> +
> +# Skip non-native targets or -shared is not supported.
> +if { ![isnative] || ![check_shared_lib_support] } {
> +    return
> +}
> +
> +proc binutils_run_test { prog } {
> +    global CC
> +    global gcc_B_opt
> +    global READELF
> +    global NM
> +    global objcopy
> +    global strip
> +    global srcdir
> +    global subdir
> +    # Add $NOPIE_CFLAGS and $NOPIE_LDFLAGS if non-PIE is required.
> +    global NOPIE_CFLAGS NOPIE_LDFLAGS
> +
> +    set sec_hdr "sec-hdr"
> +    if { "$prog" == "" } {
> +       set prog_name none
> +    } else {
> +       set prog_name $prog
> +       set ld_options ""
> +       switch -- $prog {
> +           objcopy
> +               { set prog $objcopy }
> +           strip
> +               { set prog $strip }
> +           default
> +               {
> +                   fail "Build pr25617-1a-no-sec-hdr.so ($prog_name)"
> +                   break
> +               }
> +       }
> +    }
> +
> +    run_cc_link_tests [list \
> +       [list \
> +           "Build pr25617-1a-no-sec-hdr.so ($prog_name)" \
> +           "-shared -Wl,-z,separate-code,--hash-style=sysv" \
> +           "-fPIC" \
> +           {pr25617-1a.c} \
> +           [list \
> +               [list "readelf" "-lWSDs" "pr25617-1a-$sec_hdr.rd"] \
> +               [list "nm" "-D" "pr25617-1a-no-sec-hdr.nd"] \
> +           ]\
> +           "pr25617-1a-no-sec-hdr.so" \
> +       ] \
> +       [list \
> +           "Build pr25617-1a-now-no-sec-hdr.so ($prog_name)" \
> +           "-shared -Wl,-z,separate-code,-z,now,--hash-style=gnu" \
> +           "-fPIC" \
> +           {pr25617-1a.c} \
> +           [list \
> +               [list "readelf" "-lWSDs" "pr25617-1a-$sec_hdr.rd"] \
> +               [list "nm" "-D" "pr25617-1a-no-sec-hdr.nd"] \
> +           ]\
> +           "pr25617-1a-now-no-sec-hdr.so" \
> +       ] \
> +       [list \
> +           "Build pr25617-1 (-z nosectionheader, $prog_name)" \
> +           "$NOPIE_LDFLAGS -Wl,-z,separate-code,--no-as-needed \
> +            -Wl,--hash-style=sysv -Wl,-z,nosectionheader \
> +            tmpdir/pr25617-1a-no-sec-hdr.so" \
> +           "$NOPIE_CFLAGS" \
> +           {pr25617-1b.c} \
> +           {{readelf -lWSDs pr25617-1-no-sec-hdr.rd} \
> +            {nm -D pr25617-1-no-sec-hdr.nd}} \
> +           "pr25617-1-no-sec-hdr" \
> +       ] \
> +       [list \
> +           "Build pr25617-1 (PIE, -z nosectionheader, $prog_name)" \
> +           "-pie -Wl,-z,separate-code,--no-as-needed,--hash-style=gnu \
> +            -Wl,-z,nosectionheader tmpdir/pr25617-1a-now-no-sec-hdr.so" \
> +           "-fPIE" \
> +           {pr25617-1b.c} \
> +           {{readelf -lWSDs pr25617-1-no-sec-hdr.rd} \
> +            {nm -D pr25617-1-no-sec-hdr.nd}} \
> +           "pr25617-1-pie-no-sec-hdr" \
> +       ] \
> +       [list \
> +           "Build pr25617-1 (static, -z nosectionheader, $prog_name)" \
> +           "-static -Wl,-z,separate-code -Wl,-z,nosectionheader" \
> +           "" \
> +           {pr25617-1a.c pr25617-1b.c} \
> +           {{readelf -lSWDs pr25617-1-static-no-sec-hdr.rd}} \
> +           "pr25617-1-static-no-sec-hdr" \
> +       ] \
> +    ]
> +
> +    run_ld_link_exec_tests [list \
> +       [list \
> +           "Run pr25617-1 (-z nosectionheader, $prog_name)" \
> +           "$NOPIE_LDFLAGS -Wl,-z,separate-code,--no-as-needed \
> +            -Wl,--hash-style=sysv -Wl,-z,nosectionheader \
> +            tmpdir/pr25617-1a-no-sec-hdr.so" \
> +           "" \
> +           {pr25617-1b.c} \
> +           "pr25617-1-no-sec-hdr" \
> +           "pass.out" \
> +           "$NOPIE_CFLAGS" \
> +       ] \
> +       [list \
> +           "Run pr25617-1 (PIE, -z nosectionheader, $prog_name)" \
> +           "-pie -Wl,-z,separate-code,--no-as-needed,--hash-style=gnu \
> +            -Wl,-z,nosectionheader tmpdir/pr25617-1a-now-no-sec-hdr.so" \
> +           "" \
> +           {pr25617-1b.c} \
> +           "pr25617-1-pie-no-sec-hdr" \
> +           "pass.out" \
> +           "-fPIE" \
> +       ] \
> +       [list \
> +           "Run pr25617-1 (static, -z nosectionheader, $prog_name)" \
> +           "-static -Wl,-z,separate-code -Wl,-z,nosectionheader" \
> +           "" \
> +           {pr25617-1a.c pr25617-1b.c} \
> +           "pr25617-1-static-no-sec-hdr" \
> +           "pass.out" \
> +       ] \
> +    ]
> +
> +    if { "$prog_name" != "none" } {
> +       send_log "$prog --strip-section-headers tmpdir/pr25617-1a-no-sec-hdr.so\n"
> +       set got [remote_exec host "$prog --strip-section-headers tmpdir/pr25617-1a-no-sec-hdr.so"]
> +       if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
> +           send_log "$got\n"
> +           fail "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
> +           return
> +       }
> +
> +       send_log "$READELF -lWSDs tmpdir/pr25617-1a-no-sec-hdr.so > tmpdir/dump.out\n"
> +       set got [remote_exec host "$READELF -lWSDs tmpdir/pr25617-1a-no-sec-hdr.so" "" "/dev/null" "tmpdir/dump.out"]
> +       if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
> +           send_log "$got\n"
> +           unresolved "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
> +           return
> +       }
> +
> +       if { [regexp_diff "tmpdir/dump.out" "$srcdir/$subdir/pr25617-1a-no-sec-hdr.rd"] } then {
> +           unresolved "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
> +           return
> +       }
> +
> +       send_log "$NM -D tmpdir/pr25617-1a-no-sec-hdr.so > tmpdir/dump.out\n"
> +       set got [remote_exec host "$NM -D tmpdir/pr25617-1a-no-sec-hdr.so" "" "/dev/null" "tmpdir/dump.out"]
> +       if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
> +           send_log "$got\n"
> +           unresolved "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
> +           return
> +       }
> +
> +       if { [regexp_diff "tmpdir/dump.out" "$srcdir/$subdir/pr25617-1a-no-sec-hdr.nd"] } then {
> +           unresolved "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
> +           return
> +       }
> +
> +       send_log "tmpdir/pr25617-1-no-sec-hdr > tmpdir/pr25617-1.out\n"
> +       catch "exec tmpdir/pr25617-1-no-sec-hdr > tmpdir/pr25617-1.out" got
> +       if ![string match "" $got] then {
> +           send_log "$got\n"
> +           unresolved "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
> +           return
> +       }
> +
> +       send_log "diff tmpdir/pr25617-1.out $srcdir/$subdir/pass.out\n"
> +       catch "exec diff tmpdir/pr25617-1.out $srcdir/$subdir/pass.out" got
> +       if ![string match "" $got] then {
> +           send_log "$got\n"
> +           fail "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
> +           return
> +       }
> +
> +       pass "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
> +
> +       send_log "$prog --strip-section-headers tmpdir/pr25617-1a-now-no-sec-hdr.so\n"
> +       set got [remote_exec host "$prog --strip-section-headers tmpdir/pr25617-1a-now-no-sec-hdr.so"]
> +       if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
> +           send_log "$got\n"
> +           fail "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
> +           return
> +       }
> +
> +       send_log "$READELF -lWSDs tmpdir/pr25617-1a-now-no-sec-hdr.so > tmpdir/dump.out\n"
> +       set got [remote_exec host "$READELF -lWSDs tmpdir/pr25617-1a-now-no-sec-hdr.so" "" "/dev/null" "tmpdir/dump.out"]
> +       if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
> +           send_log "$got\n"
> +           unresolved "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
> +           return
> +       }
> +
> +       if { [regexp_diff "tmpdir/dump.out" "$srcdir/$subdir/pr25617-1a-no-sec-hdr.rd"] } then {
> +           unresolved "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
> +           return
> +       }
> +
> +       send_log "$NM -D tmpdir/pr25617-1a-now-no-sec-hdr.so > tmpdir/dump.out\n"
> +       set got [remote_exec host "$NM -D tmpdir/pr25617-1a-now-no-sec-hdr.so" "" "/dev/null" "tmpdir/dump.out"]
> +       if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
> +           send_log "$got\n"
> +           unresolved "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
> +           return
> +       }
> +
> +       if { [regexp_diff "tmpdir/dump.out" "$srcdir/$subdir/pr25617-1a-no-sec-hdr.nd"] } then {
> +           unresolved "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
> +           return
> +       }
> +
> +       send_log "tmpdir/pr25617-1-pie-no-sec-hdr > tmpdir/pr25617-1-pie.out\n"
> +       catch "exec tmpdir/pr25617-1-pie-no-sec-hdr > tmpdir/pr25617-1-pie.out" got
> +       if ![string match "" $got] then {
> +           send_log "$got\n"
> +           unresolved "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
> +           return
> +       }
> +
> +       send_log "diff tmpdir/pr25617-1-pie.out $srcdir/$subdir/pass.out\n"
> +       catch "exec diff tmpdir/pr25617-1-pie.out $srcdir/$subdir/pass.out" got
> +       if ![string match "" $got] then {
> +           send_log "$got\n"
> +           fail "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
> +           return
> +       }
> +
> +       send_log "$CC $gcc_B_opt -o tmpdir/pr25617-1 tmpdir/pr25617-1b.o tmpdir/pr25617-1a-now-no-sec-hdr.so\n"
> +       catch "exec $CC $gcc_B_opt -o tmpdir/pr25617-1 tmpdir/pr25617-1b.o tmpdir/pr25617-1a-now-no-sec-hdr.so" got
> +       if ![string match "*pr25617-1a-now-no-sec-hdr.so*file in wrong format*" $got] then {
> +           send_log "$got\n"
> +           fail "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
> +           return
> +       }
> +
> +       pass "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
> +     }
> +}
> +
> +binutils_run_test ""
> +binutils_run_test objcopy
> +binutils_run_test strip
> diff --git a/ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.nd b/ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.nd
> new file mode 100644
> index 00000000000..6a96f5b55a3
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.nd
> @@ -0,0 +1,3 @@
> +#...
> +[a-f0-9 ]+ [DU] _?protected
> + + U _?test
> diff --git a/ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.rd b/ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.rd
> new file mode 100644
> index 00000000000..be49dea32db
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.rd
> @@ -0,0 +1,20 @@
> +#readelf: -lWSDs
> +
> +There are no sections in this file.
> +
> +#...
> +Program Headers:
> +  Type +Offset +VirtAddr.*
> +# On MIPS, the first segment is for .reginfo.
> +#...
> +  LOAD .*
> +#...
> +  DYNAMIC .*
> +#...
> + +Num: +Value +Size Type +Bind +Vis +Ndx Name
> + +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
> +#...
> + +[0-9]+: +[a-f0-9]+ +0 +FUNC +GLOBAL +DEFAULT +UND +__libc_start_main(@.*|)
> +#...
> + +[0-9]+: +[a-f0-9]+ +0+ +FUNC +GLOBAL +DEFAULT +UND +_?test
> +#pass
> diff --git a/ld/testsuite/ld-elf/pr25617-1-static-no-sec-hdr.rd b/ld/testsuite/ld-elf/pr25617-1-static-no-sec-hdr.rd
> new file mode 100644
> index 00000000000..92b1dc9ead9
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pr25617-1-static-no-sec-hdr.rd
> @@ -0,0 +1,12 @@
> +#readelf: -lWSDs
> +
> +There are no sections in this file.
> +
> +#...
> +Program Headers:
> +  Type +Offset +VirtAddr.*
> +# On MIPS, the first segment is for .reginfo.
> +#...
> +  LOAD .*
> +#...
> +Dynamic symbol information is not available for displaying symbols\.
> diff --git a/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd b/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd
> new file mode 100644
> index 00000000000..2813ffc6652
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd
> @@ -0,0 +1,3 @@
> +#...
> + + U _?puts(@.*|)
> +[0-9a-z]+ T _?test
> diff --git a/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd b/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd
> new file mode 100644
> index 00000000000..f7a4eec7362
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd
> @@ -0,0 +1,20 @@
> +#readelf: -lWSDs
> +
> +There are no sections in this file.
> +
> +#...
> +Program Headers:
> +  Type +Offset +VirtAddr.*
> +# On MIPS, the first segment is for .reginfo.
> +#...
> +  LOAD .*
> +#...
> +  DYNAMIC .*
> +#...
> + +Num: +Value +Size Type +Bind +Vis +Ndx Name
> + +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
> +#...
> + +[0-9]+: +[a-f0-9]+ +0 +FUNC +GLOBAL +DEFAULT +UND +_?puts(@.*|)

This test failed on PPC where readelf outputs

     7: 0000000000000000     0 FUNC    GLOBAL DEFAULT [<localentry>:
8]   UND puts@GLIBC_2.17 (2)

instead of

   7: 0000000000000000     0 FUNC    GLOBAL DEFAULT   UND puts@GLIBC_2.17 (2)

Alan, what is the best way to deal with it?

Thanks.

> +#...
> + +[0-9]+: +[a-f0-9]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +[0-9]+ +_?test
> +#pass
> diff --git a/ld/testsuite/ld-elf/pr25617-1a-sec-hdr.rd b/ld/testsuite/ld-elf/pr25617-1a-sec-hdr.rd
> new file mode 100644
> index 00000000000..9ccf0565af6
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pr25617-1a-sec-hdr.rd
> @@ -0,0 +1,19 @@
> +#readelf: -lWSDs
> +
> +There are [0-9]+ section headers, starting at offset 0x[a-f0-9]+:
> +#...
> +Program Headers:
> +  Type +Offset +VirtAddr.*
> +# On MIPS, the first segment is for .reginfo.
> +#...
> +  LOAD .*
> +#...
> +  DYNAMIC .*
> +#...
> + +Num: +Value +Size Type +Bind +Vis +Ndx Name
> + +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
> +#...
> + +[0-9]+: +[a-f0-9]+ +0 +FUNC +GLOBAL +DEFAULT +UND +_?puts(@.*|)
> +#...
> + +[0-9]+: +[a-f0-9]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +[0-9]+ +_?test
> +#pass
> diff --git a/ld/testsuite/ld-elf/pr25617-1a.c b/ld/testsuite/ld-elf/pr25617-1a.c
> new file mode 100644
> index 00000000000..f707f266fe2
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pr25617-1a.c
> @@ -0,0 +1,11 @@
> +#include <stdio.h>
> +
> +int protected = 42;
> +extern int *get_protected_ptr (void);
> +
> +void
> +test()
> +{
> +  if (&protected == get_protected_ptr ())
> +    printf ("PASS\n");
> +}
> diff --git a/ld/testsuite/ld-elf/pr25617-1b.c b/ld/testsuite/ld-elf/pr25617-1b.c
> new file mode 100644
> index 00000000000..1fd6ef45d79
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pr25617-1b.c
> @@ -0,0 +1,15 @@
> +void test(void);
> +
> +extern int protected;
> +
> +int *
> +get_protected_ptr (void)
> +{
> +  return &protected;
> +}
> +
> +int main()
> +{
> +  test();
> +  return 0;
> +}
> diff --git a/ld/testsuite/ld-elf/start-noheader.rd b/ld/testsuite/ld-elf/start-noheader.rd
> new file mode 100644
> index 00000000000..2479e340871
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/start-noheader.rd
> @@ -0,0 +1,11 @@
> +#readelf: -SlDs --wide
> +
> +There are no sections in this file.
> +
> +#...
> +Program Headers:
> +  Type +Offset +VirtAddr.*
> +# On MIPS, the first segment is for .reginfo.
> +#...
> +  LOAD .*
> +#pass
> diff --git a/ld/testsuite/ld-elf/start-shared-noheader-gnu.rd b/ld/testsuite/ld-elf/start-shared-noheader-gnu.rd
> new file mode 100644
> index 00000000000..20bc30cad4c
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/start-shared-noheader-gnu.rd
> @@ -0,0 +1,26 @@
> +#readelf: -SlDs --wide
> +
> +There are no sections in this file.
> +
> +#...
> +Program Headers:
> +  Type +Offset +VirtAddr.*
> +# On MIPS, the first segment is for .reginfo.
> +#...
> +  LOAD .*
> +#...
> +  DYNAMIC .*
> +#...
> + +Num: +Value +Size Type +Bind +Vis +Ndx Name
> + +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
> +#...
> + +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +_start
> +#...
> + +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +main
> +#...
> + +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +start
> +#...
> + +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +_main
> +#...
> + +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +__start
> +#pass
> diff --git a/ld/testsuite/ld-elf/start-shared-noheader-sysv.rd b/ld/testsuite/ld-elf/start-shared-noheader-sysv.rd
> new file mode 100644
> index 00000000000..d8f02497e58
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/start-shared-noheader-sysv.rd
> @@ -0,0 +1,26 @@
> +#readelf: -SlDs --wide
> +
> +There are no sections in this file.
> +
> +#...
> +Program Headers:
> +  Type +Offset +VirtAddr.*
> +# On MIPS, the first segment is for .reginfo.
> +#...
> +  LOAD .*
> +#...
> +  DYNAMIC .*
> +#...
> + +Num: +Value +Size Type +Bind +Vis +Ndx Name
> + +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
> +#...
> + +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +__start
> +#...
> + +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +_start
> +#...
> + +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +main
> +#...
> + +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +start
> +#...
> + +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +_main
> +#pass
> diff --git a/ld/testsuite/ld-elf/start-shared-noheader.nd b/ld/testsuite/ld-elf/start-shared-noheader.nd
> new file mode 100644
> index 00000000000..6ec6cdf8af9
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/start-shared-noheader.nd
> @@ -0,0 +1,11 @@
> +#...
> +[0-9a-z]+ A __start
> +#...
> +[0-9a-z]+ A _main
> +#...
> +[0-9a-z]+ A _start
> +#...
> +[0-9a-z]+ A main
> +#...
> +[0-9a-z]+ A start
> +#pass
> --
> 2.40.1
>


-- 
H.J.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 3/7] bfd: Improve nm and objdump without section header
  2023-06-06 17:58 ` [PATCH v4 3/7] bfd: Improve nm and objdump " H.J. Lu
@ 2023-07-01  2:12   ` Simon Marchi
  2023-07-07 15:26     ` H.J. Lu
  0 siblings, 1 reply; 17+ messages in thread
From: Simon Marchi @ 2023-07-01  2:12 UTC (permalink / raw)
  To: H.J. Lu, binutils; +Cc: Alan Modra, Florian Weimer, Kaylee Blake, gdb-patches

On 6/6/23 13:58, H.J. Lu wrote:
> When there is no section header in an executable or shared library, we
> reconstruct dynamic symbol table from the PT_DYNAMIC segment, which
> contains DT_HASH/DT_GNU_HASH/DT_MIPS_XHASH, DT_STRTAB, DT_SYMTAB,
> DT_STRSZ, and DT_SYMENT entries, to improve nm and objdump.  For DT_HASH,
> the number of dynamic symbol table entries equals the number of chains.
> For DT_GNU_HASH/DT_MIPS_XHASH, only defined symbols with non-STB_LOCAL
> indings are in hash table.  Since DT_GNU_HASH/DT_MIPS_XHASH place all
> symbols with STB_LOCAL binding before symbols with other bindings and
> all undefined symbols defined ones in dynamic symbol table, the highest
> symbol index in DT_GNU_HASH/DT_MIPS_XHASH is the highest dynamic symbol
> table index.  We can also get symbol version from DT_VERSYM, DT_VERDEF
> and DT_VERNEED entries.
> 
> dt_symtab, dt_versym, dt_verdef, dt_verneed, dt_symtab_count,
> dt_verdef_count, dt_verneed_count and dt_strtab are added to
> elf_obj_tdata to store dynamic symbol table information.

Hi,

This broke a GDB test:

    gdb/ $ make check TESTS="gdb.base/eu-strip-infcall.exp"
    FAIL: gdb.base/eu-strip-infcall.exp: gdb_breakpoint: set breakpoint at main

Looking at gdb/testsuite/gdb.log, before:

    (gdb) file /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/eu-strip-infcall/eu-strip-infcall

    Reading symbols from /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/eu-strip-infcall/eu-strip-infcall...

    Reading symbols from /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/eu-strip-infcall/eu-strip-infcall.debug...


and after:

(gdb) file /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/eu-strip-infcall/eu-strip-infcall

Reading symbols from /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/eu-strip-infcall/eu-strip-infcall...

warning: `/home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/eu-strip-infcall/eu-strip-infcall.debug': can't read symbols: file format not recognized.

(No debugging symbols found in /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/eu-strip-infcall/eu-strip-infcall)


Can you please check if it's a problem with your patch, or if it's really a malformed file?

Thanks,

Simon

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 6/7] ld: Add tests for -z nosectionheader and --strip-section-headers
  2023-06-29 20:56   ` H.J. Lu
@ 2023-07-06  1:27     ` Alan Modra
  0 siblings, 0 replies; 17+ messages in thread
From: Alan Modra @ 2023-07-06  1:27 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

On Thu, Jun 29, 2023 at 01:56:30PM -0700, H.J. Lu wrote:
> This test failed on PPC where readelf outputs
> 
>      7: 0000000000000000     0 FUNC    GLOBAL DEFAULT [<localentry>:
> 8]   UND puts@GLIBC_2.17 (2)
> 
> instead of
> 
>    7: 0000000000000000     0 FUNC    GLOBAL DEFAULT   UND puts@GLIBC_2.17 (2)
> 
> Alan, what is the best way to deal with it?

I would replace DEFAULT with DEFAULT.*, but this test has a quite a
few other problems.

We should be using run_host_cmd everywhere we invoke a compiler in the
ld testsuite, if we want to use ld/ld-new just built.  run_host_cmd
properly inserts $gcc_B_opt in cases where a user wants to test
binutils with a newly built compiler, ie. when $CC specifies -B itself.

Also, it is not good practice to exclude tests when non-native except
of course those tests that run a target binary.  Compiling and linking
often shows up problems, before you get complaints from people running
natively.

The following gives me clean results on the test, except for
mips-linux-gnu  +FAIL: Build pr25617-1a-now-no-sec-hdr.so (none)
mips-linux-gnu  +FAIL: Build pr25617-1a-now-no-sec-hdr.so (objcopy)
mips-linux-gnu  +FAIL: Build pr25617-1a-now-no-sec-hdr.so (strip)
and those are due to the .so being built with --hash-style=gnu which
results in DT_MIPS_XHASH on mips.  I'm unsure what the correct fix is
for mips, it might just be a simple readelf change.

	* testsuite/ld-elf/no-section-header.exp (binutils_run_test):
	Use run_host_cmd to invoke $CC_FOR_TARGET.  Run all tests
	non-native too, except for attempting to run the binaries.
	Run tests for ELF in general, not just linux.
	* testsuite/ld-elf/pr25617-1-no-sec-hdr.rd: Allow localentry
	symbol decoration, and support either sorting of symbols.
	* testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd: Likewise.
	* testsuite/ld-elf/pr25617-1a-sec-hdr.rd: Likewise.
	* testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd: Accept D function syms.
	* testsuite/ld-elf/start-shared-noheader-sysv.rd: Accept
	mips-sgi-irix symbol output.
	* testsuite/ld-elf/start-shared-noheader.nd: Likewise.

diff --git a/ld/testsuite/ld-elf/no-section-header.exp b/ld/testsuite/ld-elf/no-section-header.exp
index c010e572a32..bd4697ddd4c 100644
--- a/ld/testsuite/ld-elf/no-section-header.exp
+++ b/ld/testsuite/ld-elf/no-section-header.exp
@@ -21,9 +21,7 @@
 # Written by H.J. Lu (hongjiu.lu@intel.com)
 #
 
-# Make sure that binutils can correctly handle ld output in ELF.
-
-if { ![istarget *-*-linux*] } {
+if { ![is_elf_format] } {
     return
 }
 
@@ -129,14 +127,13 @@ binutils_test strip "--hash-style=gnu -shared" start \
 binutils_test strip "--hash-style=sysv -shared" start \
 	start-shared-noheader-sysv.rd start-shared-noheader.nd
 
-# Skip non-native targets or -shared is not supported.
-if { ![isnative] || ![check_shared_lib_support] } {
+
+if { ![check_compiler_available] || ![check_shared_lib_support] } {
     return
 }
 
 proc binutils_run_test { prog } {
-    global CC
-    global gcc_B_opt
+    global CC_FOR_TARGET
     global READELF
     global NM
     global objcopy
@@ -286,20 +283,22 @@ proc binutils_run_test { prog } {
 	    return
 	}
 
-	send_log "tmpdir/pr25617-1-no-sec-hdr > tmpdir/pr25617-1.out\n"
-	catch "exec tmpdir/pr25617-1-no-sec-hdr > tmpdir/pr25617-1.out" got
-	if ![string match "" $got] then {
-	    send_log "$got\n"
-	    unresolved "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
-	    return
-	}
-
-	send_log "diff tmpdir/pr25617-1.out $srcdir/$subdir/pass.out\n"
-	catch "exec diff tmpdir/pr25617-1.out $srcdir/$subdir/pass.out" got
-	if ![string match "" $got] then {
-	    send_log "$got\n"
-	    fail "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
-	    return
+	if { [isnative] } {
+	    send_log "tmpdir/pr25617-1-no-sec-hdr > tmpdir/pr25617-1.out\n"
+	    catch "exec tmpdir/pr25617-1-no-sec-hdr > tmpdir/pr25617-1.out" got
+	    if ![string match "" $got] then {
+		send_log "$got\n"
+		unresolved "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
+		return
+	    }
+
+	    send_log "diff tmpdir/pr25617-1.out $srcdir/$subdir/pass.out\n"
+	    catch "exec diff tmpdir/pr25617-1.out $srcdir/$subdir/pass.out" got
+	    if ![string match "" $got] then {
+		send_log "$got\n"
+		fail "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
+		return
+	    }
 	}
 
 	pass "Update pr25617-1a-no-sec-hdr.so ($prog_name)"
@@ -338,24 +337,25 @@ proc binutils_run_test { prog } {
 	    return
 	}
 
-	send_log "tmpdir/pr25617-1-pie-no-sec-hdr > tmpdir/pr25617-1-pie.out\n"
-	catch "exec tmpdir/pr25617-1-pie-no-sec-hdr > tmpdir/pr25617-1-pie.out" got
-	if ![string match "" $got] then {
-	    send_log "$got\n"
-	    unresolved "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
-	    return
-	}
-
-	send_log "diff tmpdir/pr25617-1-pie.out $srcdir/$subdir/pass.out\n"
-	catch "exec diff tmpdir/pr25617-1-pie.out $srcdir/$subdir/pass.out" got
-	if ![string match "" $got] then {
-	    send_log "$got\n"
-	    fail "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
-	    return
+	if { [isnative] } {
+	    send_log "tmpdir/pr25617-1-pie-no-sec-hdr > tmpdir/pr25617-1-pie.out\n"
+	    catch "exec tmpdir/pr25617-1-pie-no-sec-hdr > tmpdir/pr25617-1-pie.out" got
+	    if ![string match "" $got] then {
+		send_log "$got\n"
+		unresolved "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
+		return
+	    }
+
+	    send_log "diff tmpdir/pr25617-1-pie.out $srcdir/$subdir/pass.out\n"
+	    catch "exec diff tmpdir/pr25617-1-pie.out $srcdir/$subdir/pass.out" got
+	    if ![string match "" $got] then {
+		send_log "$got\n"
+		fail "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
+		return
+	    }
 	}
 
-	send_log "$CC $gcc_B_opt -o tmpdir/pr25617-1 tmpdir/pr25617-1b.o tmpdir/pr25617-1a-now-no-sec-hdr.so\n"
-	catch "exec $CC $gcc_B_opt -o tmpdir/pr25617-1 tmpdir/pr25617-1b.o tmpdir/pr25617-1a-now-no-sec-hdr.so" got
+	set got [run_host_cmd $CC_FOR_TARGET "-o tmpdir/pr25617-1 tmpdir/pr25617-1b.o tmpdir/pr25617-1a-now-no-sec-hdr.so"]
 	if ![string match "*pr25617-1a-now-no-sec-hdr.so*file in wrong format*" $got] then {
 	    send_log "$got\n"
 	    fail "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
diff --git a/ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.rd b/ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.rd
index be49dea32db..05957dc3e69 100644
--- a/ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.rd
+++ b/ld/testsuite/ld-elf/pr25617-1-no-sec-hdr.rd
@@ -14,7 +14,7 @@ Program Headers:
  +Num: +Value +Size Type +Bind +Vis +Ndx Name
  +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
 #...
- +[0-9]+: +[a-f0-9]+ +0 +FUNC +GLOBAL +DEFAULT +UND +__libc_start_main(@.*|)
+.* FUNC +GLOBAL +DEFAULT.* UND +(__libc_start_main(@.*|)|_?test)
 #...
- +[0-9]+: +[a-f0-9]+ +0+ +FUNC +GLOBAL +DEFAULT +UND +_?test
+.* FUNC +GLOBAL +DEFAULT.* UND +(__libc_start_main(@.*|)|_?test)
 #pass
diff --git a/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd b/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd
index 2813ffc6652..2dc92a2ff50 100644
--- a/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd
+++ b/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.nd
@@ -1,3 +1,3 @@
 #...
  + U _?puts(@.*|)
-[0-9a-z]+ T _?test
+[0-9a-z]+ [TD] _?test
diff --git a/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd b/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd
index f7a4eec7362..519ce15453e 100644
--- a/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd
+++ b/ld/testsuite/ld-elf/pr25617-1a-no-sec-hdr.rd
@@ -14,7 +14,7 @@ Program Headers:
  +Num: +Value +Size Type +Bind +Vis +Ndx Name
  +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
 #...
- +[0-9]+: +[a-f0-9]+ +0 +FUNC +GLOBAL +DEFAULT +UND +_?puts(@.*|)
+.* FUNC +GLOBAL +DEFAULT.* (UND +_?puts(@.*|)|[0-9]+ +_?test)
 #...
- +[0-9]+: +[a-f0-9]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +[0-9]+ +_?test
+.* FUNC +GLOBAL +DEFAULT.* (UND +_?puts(@.*|)|[0-9]+ +_?test)
 #pass
diff --git a/ld/testsuite/ld-elf/pr25617-1a-sec-hdr.rd b/ld/testsuite/ld-elf/pr25617-1a-sec-hdr.rd
index 9ccf0565af6..0de2915811a 100644
--- a/ld/testsuite/ld-elf/pr25617-1a-sec-hdr.rd
+++ b/ld/testsuite/ld-elf/pr25617-1a-sec-hdr.rd
@@ -13,7 +13,7 @@ Program Headers:
  +Num: +Value +Size Type +Bind +Vis +Ndx Name
  +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
 #...
- +[0-9]+: +[a-f0-9]+ +0 +FUNC +GLOBAL +DEFAULT +UND +_?puts(@.*|)
+.* FUNC +GLOBAL +DEFAULT.* (UND +_?puts(@.*|)|[0-9]+ +_?test)
 #...
- +[0-9]+: +[a-f0-9]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +[0-9]+ +_?test
+.* FUNC +GLOBAL +DEFAULT.* (UND +_?puts(@.*|)|[0-9]+ +_?test)
 #pass
diff --git a/ld/testsuite/ld-elf/start-shared-noheader-sysv.rd b/ld/testsuite/ld-elf/start-shared-noheader-sysv.rd
index d8f02497e58..d5bbb8bb6d0 100644
--- a/ld/testsuite/ld-elf/start-shared-noheader-sysv.rd
+++ b/ld/testsuite/ld-elf/start-shared-noheader-sysv.rd
@@ -14,13 +14,13 @@ Program Headers:
  +Num: +Value +Size Type +Bind +Vis +Ndx Name
  +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
 #...
- +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +__start
+.* GLOBAL +DEFAULT.* __start
 #...
- +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +_start
+.* GLOBAL +DEFAULT.* _start
 #...
- +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +main
+.* GLOBAL +DEFAULT.* main
 #...
- +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +start
+.* GLOBAL +DEFAULT.* start
 #...
- +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +_main
+.* GLOBAL +DEFAULT.* _main
 #pass
diff --git a/ld/testsuite/ld-elf/start-shared-noheader.nd b/ld/testsuite/ld-elf/start-shared-noheader.nd
index 6ec6cdf8af9..d1e7dd11fd4 100644
--- a/ld/testsuite/ld-elf/start-shared-noheader.nd
+++ b/ld/testsuite/ld-elf/start-shared-noheader.nd
@@ -1,11 +1,11 @@
 #...
-[0-9a-z]+ A __start
+[0-9a-z]+ [AD] __start
 #...
-[0-9a-z]+ A _main
+[0-9a-z]+ [AD] _main
 #...
-[0-9a-z]+ A _start
+[0-9a-z]+ [AD] _start
 #...
-[0-9a-z]+ A main
+[0-9a-z]+ [AD] main
 #...
-[0-9a-z]+ A start
+[0-9a-z]+ [AD] start
 #pass


-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 3/7] bfd: Improve nm and objdump without section header
  2023-07-01  2:12   ` Simon Marchi
@ 2023-07-07 15:26     ` H.J. Lu
  2023-07-10  3:30       ` Simon Marchi
  0 siblings, 1 reply; 17+ messages in thread
From: H.J. Lu @ 2023-07-07 15:26 UTC (permalink / raw)
  To: Simon Marchi
  Cc: binutils, Alan Modra, Florian Weimer, Kaylee Blake, gdb-patches

On Fri, Jun 30, 2023 at 7:12 PM Simon Marchi <simon.marchi@polymtl.ca> wrote:
>
> On 6/6/23 13:58, H.J. Lu wrote:
> > When there is no section header in an executable or shared library, we
> > reconstruct dynamic symbol table from the PT_DYNAMIC segment, which
> > contains DT_HASH/DT_GNU_HASH/DT_MIPS_XHASH, DT_STRTAB, DT_SYMTAB,
> > DT_STRSZ, and DT_SYMENT entries, to improve nm and objdump.  For DT_HASH,
> > the number of dynamic symbol table entries equals the number of chains.
> > For DT_GNU_HASH/DT_MIPS_XHASH, only defined symbols with non-STB_LOCAL
> > indings are in hash table.  Since DT_GNU_HASH/DT_MIPS_XHASH place all
> > symbols with STB_LOCAL binding before symbols with other bindings and
> > all undefined symbols defined ones in dynamic symbol table, the highest
> > symbol index in DT_GNU_HASH/DT_MIPS_XHASH is the highest dynamic symbol
> > table index.  We can also get symbol version from DT_VERSYM, DT_VERDEF
> > and DT_VERNEED entries.
> >
> > dt_symtab, dt_versym, dt_verdef, dt_verneed, dt_symtab_count,
> > dt_verdef_count, dt_verneed_count and dt_strtab are added to
> > elf_obj_tdata to store dynamic symbol table information.
>
> Hi,
>
> This broke a GDB test:
>
>     gdb/ $ make check TESTS="gdb.base/eu-strip-infcall.exp"
>     FAIL: gdb.base/eu-strip-infcall.exp: gdb_breakpoint: set breakpoint at main
>
> Looking at gdb/testsuite/gdb.log, before:
>
>     (gdb) file /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/eu-strip-infcall/eu-strip-infcall
>
>     Reading symbols from /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/eu-strip-infcall/eu-strip-infcall...
>
>     Reading symbols from /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/eu-strip-infcall/eu-strip-infcall.debug...
>
>
> and after:
>
> (gdb) file /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/eu-strip-infcall/eu-strip-infcall
>
> Reading symbols from /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/eu-strip-infcall/eu-strip-infcall...
>
> warning: `/home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/eu-strip-infcall/eu-strip-infcall.debug': can't read symbols: file format not recognized.
>
> (No debugging symbols found in /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/eu-strip-infcall/eu-strip-infcall)
>
>
> Can you please check if it's a problem with your patch, or if it's really a malformed file?
>
> Thanks,
>
> Simon

It works for me:

$ make check TESTS="gdb.base/eu-strip-infcall.exp"
....
=== gdb Summary ===

# of expected passes 1

My change only impacts files without section header. eu-strip-infcall.exp does
"eu-strip -f ${binfile}.debug $binfile", which doesn't remove section header.

-- 
H.J.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 3/7] bfd: Improve nm and objdump without section header
  2023-07-07 15:26     ` H.J. Lu
@ 2023-07-10  3:30       ` Simon Marchi
  2023-07-13  5:02         ` Alan Modra
  0 siblings, 1 reply; 17+ messages in thread
From: Simon Marchi @ 2023-07-10  3:30 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils, Alan Modra, Florian Weimer, Kaylee Blake, gdb-patches


> It works for me:
> 
> $ make check TESTS="gdb.base/eu-strip-infcall.exp"
> ....
> === gdb Summary ===
> 
> # of expected passes 1
> 
> My change only impacts files without section header. eu-strip-infcall.exp does
> "eu-strip -f ${binfile}.debug $binfile", which doesn't remove section header.
> 

I can reliably reproduce the problem on two separate machine, one Ubuntu
22.04 and one failrly up to date Arch Linux.  elfutils version 0.186 and
0.189, respectively.

It goes wrong when GDB does a bfd_check_format call on
testsuite/outputs/gdb.base/eu-strip-infcall/eu-strip-infcall.debug.
Before you commit it works, and after your commit it returns false.  It
happens in this new statement added to elf_object_p, added by the commit:

	      if ((i_phdr->p_offset + i_phdr->p_filesz) > filesize)
		goto got_no_match;

(top-gdb) p i_phdr->p_offset
$1 = 8192
(top-gdb) p i_phdr->p_filesz
$2 = 196
(top-gdb) p filesize
$3 = 5104
(top-gdb) p i
$4 = 4

It would be this program header causing the condition to fail:

  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  ...
  LOAD           0x002000 0x0000000000002000 0x0000000000002000 0x0000c4 0x0000c4 R   0x1000

So, the program header of the .debug file describes the segments of the
main binary, not sure if that's expected.

Simon

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 3/7] bfd: Improve nm and objdump without section header
  2023-07-10  3:30       ` Simon Marchi
@ 2023-07-13  5:02         ` Alan Modra
  2023-07-13  5:34           ` Fangrui Song
  2023-07-13 21:58           ` Mark Wielaard
  0 siblings, 2 replies; 17+ messages in thread
From: Alan Modra @ 2023-07-13  5:02 UTC (permalink / raw)
  To: Simon Marchi; +Cc: H.J. Lu, binutils, Florian Weimer, Kaylee Blake, gdb-patches

On Sun, Jul 09, 2023 at 11:30:01PM -0400, Simon Marchi wrote:
> 
> > It works for me:
> > 
> > $ make check TESTS="gdb.base/eu-strip-infcall.exp"
> > ....
> > === gdb Summary ===
> > 
> > # of expected passes 1
> > 
> > My change only impacts files without section header. eu-strip-infcall.exp does
> > "eu-strip -f ${binfile}.debug $binfile", which doesn't remove section header.
> > 
> 
> I can reliably reproduce the problem on two separate machine, one Ubuntu
> 22.04 and one failrly up to date Arch Linux.  elfutils version 0.186 and
> 0.189, respectively.
> 
> It goes wrong when GDB does a bfd_check_format call on
> testsuite/outputs/gdb.base/eu-strip-infcall/eu-strip-infcall.debug.
> Before you commit it works, and after your commit it returns false.  It
> happens in this new statement added to elf_object_p, added by the commit:
> 
> 	      if ((i_phdr->p_offset + i_phdr->p_filesz) > filesize)
> 		goto got_no_match;
> 
> (top-gdb) p i_phdr->p_offset
> $1 = 8192
> (top-gdb) p i_phdr->p_filesz
> $2 = 196
> (top-gdb) p filesize
> $3 = 5104
> (top-gdb) p i
> $4 = 4
> 
> It would be this program header causing the condition to fail:
> 
>   Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
>   ...
>   LOAD           0x002000 0x0000000000002000 0x0000000000002000 0x0000c4 0x0000c4 R   0x1000
> 
> So, the program header of the .debug file describes the segments of the
> main binary, not sure if that's expected.

No, that's not expected.  Program headers in a .debug file ought to
describe the contents of the debug file.  You'll typically see many
with p_filesz zero.  eu-strip appears to be broken in this respect.

There is another problem with the code added to elf_object_p:
_bfd_elf_get_dynamic_symbols is told that it can access up to e_phnum
program headers, but they very likely haven't all been swapped in.

I'm going to apply the following patch.
----

elf_object_p load of dynamic symbols

This fixes an uninitialised memory access on a fuzzed file:
0 0xf22e9b in offset_from_vma /src/binutils-gdb/bfd/elf.c:1899:2
1 0xf1e90f in _bfd_elf_get_dynamic_symbols /src/binutils-gdb/bfd/elf.c:2099:13
2 0x10e6a54 in bfd_elf32_object_p /src/binutils-gdb/bfd/elfcode.h:851:9

Hopefully it will also stop any attempt to load dynamic symbols from
eu-strip debug files.

	* elfcode.h (elf_object_p): Do not attempt to load dynamic
	symbols for a file with no section headers until all the
	program headers are swapped in.  Do not fail on eu-strip debug
	files.

diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index aae66bcebf8..b2277921680 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -819,6 +819,7 @@ elf_object_p (bfd *abfd)
 	goto got_no_match;
       if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_phoff, SEEK_SET) != 0)
 	goto got_no_match;
+      bool eu_strip_broken_phdrs = false;
       i_phdr = elf_tdata (abfd)->phdr;
       for (i = 0; i < i_ehdrp->e_phnum; i++, i_phdr++)
 	{
@@ -839,21 +840,31 @@ elf_object_p (bfd *abfd)
 		  abfd->read_only = 1;
 		}
 	    }
-	  if (i_phdr->p_filesz != 0)
-	    {
-	      if ((i_phdr->p_offset + i_phdr->p_filesz) > filesize)
-		goto got_no_match;
-	      /* Try to reconstruct dynamic symbol table from PT_DYNAMIC
-		 segment if there is no section header.  */
-	      if (i_phdr->p_type == PT_DYNAMIC
-		  && i_ehdrp->e_shstrndx == 0
-		  && i_ehdrp->e_shoff == 0
-		  && !_bfd_elf_get_dynamic_symbols (abfd, i_phdr,
-						    elf_tdata (abfd)->phdr,
-						    i_ehdrp->e_phnum,
-						    filesize))
-		goto got_no_match;
-	    }
+	  /* Detect eu-strip -f debug files, which have program
+	     headers that describe the original file.  */
+	  if (i_phdr->p_filesz != 0
+	      && (i_phdr->p_filesz > filesize
+		  || i_phdr->p_offset > filesize - i_phdr->p_filesz))
+	    eu_strip_broken_phdrs = true;
+	}
+      if (!eu_strip_broken_phdrs
+	  && i_ehdrp->e_shoff == 0
+	  && i_ehdrp->e_shstrndx == 0)
+	{
+	  /* Try to reconstruct dynamic symbol table from PT_DYNAMIC
+	     segment if there is no section header.  */
+	  i_phdr = elf_tdata (abfd)->phdr;
+	  for (i = 0; i < i_ehdrp->e_phnum; i++, i_phdr++)
+	    if (i_phdr->p_type == PT_DYNAMIC)
+	      {
+		if (i_phdr->p_filesz != 0
+		    && !_bfd_elf_get_dynamic_symbols (abfd, i_phdr,
+						      elf_tdata (abfd)->phdr,
+						      i_ehdrp->e_phnum,
+						      filesize))
+		  goto got_no_match;
+		break;
+	      }
 	}
     }
 

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 3/7] bfd: Improve nm and objdump without section header
  2023-07-13  5:02         ` Alan Modra
@ 2023-07-13  5:34           ` Fangrui Song
  2023-07-13 21:58           ` Mark Wielaard
  1 sibling, 0 replies; 17+ messages in thread
From: Fangrui Song @ 2023-07-13  5:34 UTC (permalink / raw)
  To: Alan Modra, Simon Marchi
  Cc: H.J. Lu, binutils, Florian Weimer, Kaylee Blake, gdb-patches

On Wed, Jul 12, 2023 at 10:02 PM Alan Modra via Binutils
<binutils@sourceware.org> wrote:
>
> On Sun, Jul 09, 2023 at 11:30:01PM -0400, Simon Marchi wrote:
> >
> > > It works for me:
> > >
> > > $ make check TESTS="gdb.base/eu-strip-infcall.exp"
> > > ....
> > > === gdb Summary ===
> > >
> > > # of expected passes 1
> > >
> > > My change only impacts files without section header. eu-strip-infcall.exp does
> > > "eu-strip -f ${binfile}.debug $binfile", which doesn't remove section header.
> > >
> >
> > I can reliably reproduce the problem on two separate machine, one Ubuntu
> > 22.04 and one failrly up to date Arch Linux.  elfutils version 0.186 and
> > 0.189, respectively.
> >
> > It goes wrong when GDB does a bfd_check_format call on
> > testsuite/outputs/gdb.base/eu-strip-infcall/eu-strip-infcall.debug.
> > Before you commit it works, and after your commit it returns false.  It
> > happens in this new statement added to elf_object_p, added by the commit:
> >
> >             if ((i_phdr->p_offset + i_phdr->p_filesz) > filesize)
> >               goto got_no_match;
> >
> > (top-gdb) p i_phdr->p_offset
> > $1 = 8192
> > (top-gdb) p i_phdr->p_filesz
> > $2 = 196
> > (top-gdb) p filesize
> > $3 = 5104
> > (top-gdb) p i
> > $4 = 4
> >
> > It would be this program header causing the condition to fail:
> >
> >   Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
> >   ...
> >   LOAD           0x002000 0x0000000000002000 0x0000000000002000 0x0000c4 0x0000c4 R   0x1000
> >
> > So, the program header of the .debug file describes the segments of the
> > main binary, not sure if that's expected.
>
> No, that's not expected.  Program headers in a .debug file ought to
> describe the contents of the debug file.  You'll typically see many
> with p_filesz zero.  eu-strip appears to be broken in this respect.

Do you have a bug number for eu-strip ? It seems good to keep a
reference of the bug
so that we can track it.

> There is another problem with the code added to elf_object_p:
> _bfd_elf_get_dynamic_symbols is told that it can access up to e_phnum
> program headers, but they very likely haven't all been swapped in.
>
> I'm going to apply the following patch.
> ----
>
> elf_object_p load of dynamic symbols
>
> This fixes an uninitialised memory access on a fuzzed file:
> 0 0xf22e9b in offset_from_vma /src/binutils-gdb/bfd/elf.c:1899:2
> 1 0xf1e90f in _bfd_elf_get_dynamic_symbols /src/binutils-gdb/bfd/elf.c:2099:13
> 2 0x10e6a54 in bfd_elf32_object_p /src/binutils-gdb/bfd/elfcode.h:851:9
>
> Hopefully it will also stop any attempt to load dynamic symbols from
> eu-strip debug files.
>
>         * elfcode.h (elf_object_p): Do not attempt to load dynamic
>         symbols for a file with no section headers until all the
>         program headers are swapped in.  Do not fail on eu-strip debug
>         files.
>
> diff --git a/bfd/elfcode.h b/bfd/elfcode.h
> index aae66bcebf8..b2277921680 100644
> --- a/bfd/elfcode.h
> +++ b/bfd/elfcode.h
> @@ -819,6 +819,7 @@ elf_object_p (bfd *abfd)
>         goto got_no_match;
>        if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_phoff, SEEK_SET) != 0)
>         goto got_no_match;
> +      bool eu_strip_broken_phdrs = false;
>        i_phdr = elf_tdata (abfd)->phdr;
>        for (i = 0; i < i_ehdrp->e_phnum; i++, i_phdr++)
>         {
> @@ -839,21 +840,31 @@ elf_object_p (bfd *abfd)
>                   abfd->read_only = 1;
>                 }
>             }
> -         if (i_phdr->p_filesz != 0)
> -           {
> -             if ((i_phdr->p_offset + i_phdr->p_filesz) > filesize)
> -               goto got_no_match;
> -             /* Try to reconstruct dynamic symbol table from PT_DYNAMIC
> -                segment if there is no section header.  */
> -             if (i_phdr->p_type == PT_DYNAMIC
> -                 && i_ehdrp->e_shstrndx == 0
> -                 && i_ehdrp->e_shoff == 0
> -                 && !_bfd_elf_get_dynamic_symbols (abfd, i_phdr,
> -                                                   elf_tdata (abfd)->phdr,
> -                                                   i_ehdrp->e_phnum,
> -                                                   filesize))
> -               goto got_no_match;
> -           }
> +         /* Detect eu-strip -f debug files, which have program
> +            headers that describe the original file.  */
> +         if (i_phdr->p_filesz != 0
> +             && (i_phdr->p_filesz > filesize
> +                 || i_phdr->p_offset > filesize - i_phdr->p_filesz))
> +           eu_strip_broken_phdrs = true;
> +       }
> +      if (!eu_strip_broken_phdrs
> +         && i_ehdrp->e_shoff == 0
> +         && i_ehdrp->e_shstrndx == 0)
> +       {
> +         /* Try to reconstruct dynamic symbol table from PT_DYNAMIC
> +            segment if there is no section header.  */
> +         i_phdr = elf_tdata (abfd)->phdr;
> +         for (i = 0; i < i_ehdrp->e_phnum; i++, i_phdr++)
> +           if (i_phdr->p_type == PT_DYNAMIC)
> +             {
> +               if (i_phdr->p_filesz != 0
> +                   && !_bfd_elf_get_dynamic_symbols (abfd, i_phdr,
> +                                                     elf_tdata (abfd)->phdr,
> +                                                     i_ehdrp->e_phnum,
> +                                                     filesize))
> +                 goto got_no_match;
> +               break;
> +             }
>         }
>      }
>
>
> --
> Alan Modra
> Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 3/7] bfd: Improve nm and objdump without section header
  2023-07-13  5:02         ` Alan Modra
  2023-07-13  5:34           ` Fangrui Song
@ 2023-07-13 21:58           ` Mark Wielaard
  2023-07-19  6:21             ` Alan Modra
  1 sibling, 1 reply; 17+ messages in thread
From: Mark Wielaard @ 2023-07-13 21:58 UTC (permalink / raw)
  To: Alan Modra
  Cc: Simon Marchi, H.J. Lu, binutils, Florian Weimer, Kaylee Blake,
	gdb-patches, Ryan Goldberg, Matthias Klose, nickc

Hi,

On Thu, Jul 13, 2023 at 02:32:25PM +0930, Alan Modra via Binutils wrote:
> > So, the program header of the .debug file describes the segments of the
> > main binary, not sure if that's expected.
> 
> No, that's not expected.  Program headers in a .debug file ought to
> describe the contents of the debug file.  You'll typically see many
> with p_filesz zero.  eu-strip appears to be broken in this respect.

It is by design that eu-strip -f copies over the program headers of
the main file into the .debug file. It would be nice to tag .debug
files as such, to prevent issues like this. There is a binutils bug
about it: https://sourceware.org/bugzilla/show_bug.cgi?id=22136

> There is another problem with the code added to elf_object_p:
> _bfd_elf_get_dynamic_symbols is told that it can access up to e_phnum
> program headers, but they very likely haven't all been swapped in.
> 
> I'm going to apply the following patch.
>
> ----
> 
> elf_object_p load of dynamic symbols
> 
> This fixes an uninitialised memory access on a fuzzed file:
> 0 0xf22e9b in offset_from_vma /src/binutils-gdb/bfd/elf.c:1899:2
> 1 0xf1e90f in _bfd_elf_get_dynamic_symbols /src/binutils-gdb/bfd/elf.c:2099:13
> 2 0x10e6a54 in bfd_elf32_object_p /src/binutils-gdb/bfd/elfcode.h:851:9
> 
> Hopefully it will also stop any attempt to load dynamic symbols from
> eu-strip debug files.
> 
> 	* elfcode.h (elf_object_p): Do not attempt to load dynamic
> 	symbols for a file with no section headers until all the
> 	program headers are swapped in.  Do not fail on eu-strip debug
> 	files.

Thanks! This does resolves an elfutils/debuginfod issue Ryan and I
were tracking down on debian-testing with using binutils objcopy
extracting sections from a .debug file. Debian testing ships with
binutils 2.40.90.20230705.

If possible could this go into 2.41 (and in an update for Debian
testing)?

Thanks,

Mark

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 3/7] bfd: Improve nm and objdump without section header
  2023-07-13 21:58           ` Mark Wielaard
@ 2023-07-19  6:21             ` Alan Modra
  0 siblings, 0 replies; 17+ messages in thread
From: Alan Modra @ 2023-07-19  6:21 UTC (permalink / raw)
  To: Mark Wielaard; +Cc: binutils, nickc

On Thu, Jul 13, 2023 at 11:58:08PM +0200, Mark Wielaard wrote:
> If possible could this go into 2.41

Done.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2023-07-19  6:21 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-06 17:58 [PATCH v4 0/7] ELF: Strip section header in ELF objects H.J. Lu
2023-06-06 17:58 ` [PATCH v4 1/7] " H.J. Lu
2023-06-06 17:58 ` [PATCH v4 2/7] ELF: Discard non-alloc sections without section header H.J. Lu
2023-06-06 17:58 ` [PATCH v4 3/7] bfd: Improve nm and objdump " H.J. Lu
2023-07-01  2:12   ` Simon Marchi
2023-07-07 15:26     ` H.J. Lu
2023-07-10  3:30       ` Simon Marchi
2023-07-13  5:02         ` Alan Modra
2023-07-13  5:34           ` Fangrui Song
2023-07-13 21:58           ` Mark Wielaard
2023-07-19  6:21             ` Alan Modra
2023-06-06 17:58 ` [PATCH v4 4/7] ld: Add simple tests for -z nosectionheader H.J. Lu
2023-06-06 17:58 ` [PATCH v4 5/7] binutils: Add a --strip-section-headers test H.J. Lu
2023-06-06 17:58 ` [PATCH v4 6/7] ld: Add tests for -z nosectionheader and --strip-section-headers H.J. Lu
2023-06-29 20:56   ` H.J. Lu
2023-07-06  1:27     ` Alan Modra
2023-06-06 17:58 ` [PATCH v4 7/7] ld: Add -z nosectionheader test to bootstrap.exp H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).