* [PATCH v3 0/7] ELF: Strip section header in ELF objects
@ 2023-06-05 15:32 H.J. Lu
2023-06-05 15:32 ` [PATCH v3 1/7] " H.J. Lu
` (7 more replies)
0 siblings, 8 replies; 15+ messages in thread
From: H.J. Lu @ 2023-06-05 15:32 UTC (permalink / raw)
To: binutils; +Cc: Alan Modra, Kaylee Blake
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 a simple test for -z nosectionheader
bfd/bfd-in2.h | 6 +-
bfd/bfd.c | 6 +-
bfd/elf-bfd.h | 15 +
bfd/elf.c | 755 ++++++++++++++++--
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 | 8 +
ld/testsuite/ld-bootstrap/bootstrap.exp | 10 +-
ld/testsuite/ld-elf/hash-2.d | 11 +
ld/testsuite/ld-elf/no-section-header.exp | 370 +++++++++
ld/testsuite/ld-elf/nosectionheader.d | 14 +
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 +
34 files changed, 1478 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.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] 15+ messages in thread
* [PATCH v3 1/7] ELF: Strip section header in ELF objects
2023-06-05 15:32 [PATCH v3 0/7] ELF: Strip section header in ELF objects H.J. Lu
@ 2023-06-05 15:32 ` H.J. Lu
2023-06-05 15:32 ` [PATCH v3 2/7] ELF: Discard non-alloc sections without section header H.J. Lu
` (6 subsequent siblings)
7 siblings, 0 replies; 15+ messages in thread
From: H.J. Lu @ 2023-06-05 15:32 UTC (permalink / raw)
To: binutils; +Cc: Alan Modra, 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-0X-XX 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-0X-XX 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-0X-XX 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.
(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 | 8 ++++++++
13 files changed, 110 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 71debd73733..014b7a90a4d 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..37479189154 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -1971,6 +1971,10 @@ parse_args (unsigned argc, char **argv)
break;
}
+ /* -z nosectionheader implies --strip-all. */
+ if (config.no_section_header)
+ link_info.strip = strip_all;
+
if (!bfd_link_dll (&link_info))
{
if (command_line.filter_shlib)
@@ -2245,6 +2249,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] 15+ messages in thread
* [PATCH v3 2/7] ELF: Discard non-alloc sections without section header
2023-06-05 15:32 [PATCH v3 0/7] ELF: Strip section header in ELF objects H.J. Lu
2023-06-05 15:32 ` [PATCH v3 1/7] " H.J. Lu
@ 2023-06-05 15:32 ` H.J. Lu
2023-06-05 15:32 ` [PATCH v3 3/7] bfd: Improve nm and objdump " H.J. Lu
` (5 subsequent siblings)
7 siblings, 0 replies; 15+ messages in thread
From: H.J. Lu @ 2023-06-05 15:32 UTC (permalink / raw)
To: binutils; +Cc: Alan Modra, 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 | 5 +++++
ld/ldlang.c | 4 ++++
3 files changed, 19 insertions(+), 3 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..f1100b8c1e9 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
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] 15+ messages in thread
* [PATCH v3 3/7] bfd: Improve nm and objdump without section header
2023-06-05 15:32 [PATCH v3 0/7] ELF: Strip section header in ELF objects H.J. Lu
2023-06-05 15:32 ` [PATCH v3 1/7] " H.J. Lu
2023-06-05 15:32 ` [PATCH v3 2/7] ELF: Discard non-alloc sections without section header H.J. Lu
@ 2023-06-05 15:32 ` H.J. Lu
2023-06-06 6:44 ` Alan Modra
2023-06-05 15:32 ` [PATCH v3 4/7] ld: Add a simple test for -z nosectionheader H.J. Lu
` (4 subsequent siblings)
7 siblings, 1 reply; 15+ messages in thread
From: H.J. Lu @ 2023-06-05 15:32 UTC (permalink / raw)
To: binutils; +Cc: Alan Modra, 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 | 742 ++++++++++++++++++++++++++++++++++++++++++++++----
bfd/elfcode.h | 55 +++-
bfd/elflink.c | 12 +
4 files changed, 759 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..3ab44a8e02e 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,564 @@ _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 (file_ptr) (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 the size_t type is smaller than the bfd_size_type, eg because
+ you are building a 32-bit tool on a 64-bit host, then make sure
+ that when (number) is cast to (size_t) no information is lost. */
+ if (sizeof (size_t) < sizeof (bfd_size_type)
+ && (bfd_size_type) ((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;
+ if (dynbuf != NULL)
+ free (dynbuf);
+ if (esymbuf != NULL)
+ free (esymbuf);
+ if (gnubuckets != NULL)
+ free (gnubuckets);
+ if (gnuchains != NULL)
+ free (gnuchains);
+ if (mipsxlat != NULL)
+ 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;
+ }
+
+ /* NB: Don't place this section in output. */
+ if (sec && 0)
+ sec->output_section = bfd_abs_section_ptr;
+
+ 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 +2451,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 +9181,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 +9196,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 +9405,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 +9462,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 +9476,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 +9513,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 +9558,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 +9573,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 +9665,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 +9708,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 +9749,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] 15+ messages in thread
* [PATCH v3 4/7] ld: Add a simple test for -z nosectionheader
2023-06-05 15:32 [PATCH v3 0/7] ELF: Strip section header in ELF objects H.J. Lu
` (2 preceding siblings ...)
2023-06-05 15:32 ` [PATCH v3 3/7] bfd: Improve nm and objdump " H.J. Lu
@ 2023-06-05 15:32 ` H.J. Lu
2023-06-05 15:32 ` [PATCH v3 5/7] binutils: Add a --strip-section-headers test H.J. Lu
` (3 subsequent siblings)
7 siblings, 0 replies; 15+ messages in thread
From: H.J. Lu @ 2023-06-05 15:32 UTC (permalink / raw)
To: binutils; +Cc: Alan Modra, Kaylee Blake
From: Kaylee Blake <klkblake@gmail.com>
2020-03-XX Kaylee Blake <klkblake@gmail.com>
PR ld/25617
* testsuite/ld-elf/nosectionheader.d: New file.
---
| 14 ++++++++++++++
1 file changed, 14 insertions(+)
create mode 100644 ld/testsuite/ld-elf/nosectionheader.d
--git a/ld/testsuite/ld-elf/nosectionheader.d b/ld/testsuite/ld-elf/nosectionheader.d
new file mode 100644
index 00000000000..cbaea669b9a
--- /dev/null
+++ b/ld/testsuite/ld-elf/nosectionheader.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.
--
2.40.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v3 5/7] binutils: Add a --strip-section-headers test
2023-06-05 15:32 [PATCH v3 0/7] ELF: Strip section header in ELF objects H.J. Lu
` (3 preceding siblings ...)
2023-06-05 15:32 ` [PATCH v3 4/7] ld: Add a simple test for -z nosectionheader H.J. Lu
@ 2023-06-05 15:32 ` H.J. Lu
2023-06-05 15:32 ` [PATCH v3 6/7] ld: Add tests for -z nosectionheader and --strip-section-headers H.J. Lu
` (2 subsequent siblings)
7 siblings, 0 replies; 15+ messages in thread
From: H.J. Lu @ 2023-06-05 15:32 UTC (permalink / raw)
To: binutils; +Cc: Alan Modra, 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 +++++
| 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 361e430f119..41add0fecda 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"
--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] 15+ messages in thread
* [PATCH v3 6/7] ld: Add tests for -z nosectionheader and --strip-section-headers
2023-06-05 15:32 [PATCH v3 0/7] ELF: Strip section header in ELF objects H.J. Lu
` (4 preceding siblings ...)
2023-06-05 15:32 ` [PATCH v3 5/7] binutils: Add a --strip-section-headers test H.J. Lu
@ 2023-06-05 15:32 ` H.J. Lu
2023-06-06 6:46 ` Alan Modra
2023-06-06 9:57 ` Florian Weimer
2023-06-05 15:32 ` [PATCH v3 7/7] ld: Add -z nosectionheader test to bootstrap.exp H.J. Lu
2023-06-06 6:48 ` [PATCH v3 0/7] ELF: Strip section header in ELF objects Alan Modra
7 siblings, 2 replies; 15+ messages in thread
From: H.J. Lu @ 2023-06-05 15:32 UTC (permalink / raw)
To: binutils; +Cc: Alan Modra, 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 +
| 370 ++++++++++++++++++
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 +
| 11 +
| 26 ++
| 26 ++
| 11 +
14 files changed, 558 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
--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..4ed3f9551a9
--- /dev/null
+++ b/ld/testsuite/ld-elf/no-section-header.exp
@@ -0,0 +1,370 @@
+# Expect script for -z nosectionheader and --strip-section-headers tests
+# Copyright (C) 2020 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)"
+ }
+
+ 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;
+}
--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
--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
--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
--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] 15+ messages in thread
* [PATCH v3 7/7] ld: Add -z nosectionheader test to bootstrap.exp
2023-06-05 15:32 [PATCH v3 0/7] ELF: Strip section header in ELF objects H.J. Lu
` (5 preceding siblings ...)
2023-06-05 15:32 ` [PATCH v3 6/7] ld: Add tests for -z nosectionheader and --strip-section-headers H.J. Lu
@ 2023-06-05 15:32 ` H.J. Lu
2023-06-06 6:48 ` [PATCH v3 0/7] ELF: Strip section header in ELF objects Alan Modra
7 siblings, 0 replies; 15+ messages in thread
From: H.J. Lu @ 2023-06-05 15:32 UTC (permalink / raw)
To: binutils; +Cc: Alan Modra, 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] 15+ messages in thread
* Re: [PATCH v3 3/7] bfd: Improve nm and objdump without section header
2023-06-05 15:32 ` [PATCH v3 3/7] bfd: Improve nm and objdump " H.J. Lu
@ 2023-06-06 6:44 ` Alan Modra
0 siblings, 0 replies; 15+ messages in thread
From: Alan Modra @ 2023-06-06 6:44 UTC (permalink / raw)
To: H.J. Lu; +Cc: binutils, Kaylee Blake
On Mon, Jun 05, 2023 at 08:32:18AM -0700, H.J. Lu wrote:
> --- 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))
Nitpick: excess parentheses.
> + {
> + 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,564 @@ _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 (file_ptr) (vma - seg->p_vaddr + seg->p_offset);
No need for the cast here (and then no need for parens).
> + }
> +
> + 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 the size_t type is smaller than the bfd_size_type, eg because
> + you are building a 32-bit tool on a 64-bit host, then make sure
> + that when (number) is cast to (size_t) no information is lost. */
> + if (sizeof (size_t) < sizeof (bfd_size_type)
> + && (bfd_size_type) ((size_t) number) != number)
> + {
Just "if ((size_t) number != number)" will do.
> + 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);
These are all bfd_alloc by the look of it, and we'll have file size
sanity checks done before any alloc. Good!
> +
> + res = true;
> +
> + error_return:
> + /* Restore file position for elf_object_p. */
> + if (bfd_seek (abfd, saved_filepos, SEEK_SET) != 0)
> + res = false;
> + if (dynbuf != NULL)
> + free (dynbuf);
> + if (esymbuf != NULL)
> + free (esymbuf);
> + if (gnubuckets != NULL)
> + free (gnubuckets);
> + if (gnuchains != NULL)
> + free (gnuchains);
> + if (mipsxlat != NULL)
> + free (mipsxlat);
These days we just write free (x) without if (x != NULL).
> + 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;
> + }
> +
> + /* NB: Don't place this section in output. */
> + if (sec && 0)
> + sec->output_section = bfd_abs_section_ptr;
Please delete this rather than leaving it disabled, and delete the comment.
> +
> + 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 +2451,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 +9181,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 +9196,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 +9405,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 +9462,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 +9476,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 +9513,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 +9558,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 +9573,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 +9665,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 +9708,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 +9749,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
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 6/7] ld: Add tests for -z nosectionheader and --strip-section-headers
2023-06-05 15:32 ` [PATCH v3 6/7] ld: Add tests for -z nosectionheader and --strip-section-headers H.J. Lu
@ 2023-06-06 6:46 ` Alan Modra
2023-06-06 17:26 ` H.J. Lu
2023-06-06 9:57 ` Florian Weimer
1 sibling, 1 reply; 15+ messages in thread
From: Alan Modra @ 2023-06-06 6:46 UTC (permalink / raw)
To: H.J. Lu; +Cc: binutils, Kaylee Blake
On Mon, Jun 05, 2023 at 08:32:21AM -0700, H.J. Lu wrote:
> + 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)"
Needs a return here, otherwise you might get both a fail and a pass.
> + }
> +
> + pass "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
> + }
> +}
> +
> +binutils_run_test ""
> +binutils_run_test objcopy
> +binutils_run_test strip
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 0/7] ELF: Strip section header in ELF objects
2023-06-05 15:32 [PATCH v3 0/7] ELF: Strip section header in ELF objects H.J. Lu
` (6 preceding siblings ...)
2023-06-05 15:32 ` [PATCH v3 7/7] ld: Add -z nosectionheader test to bootstrap.exp H.J. Lu
@ 2023-06-06 6:48 ` Alan Modra
2023-06-29 17:21 ` H.J. Lu
7 siblings, 1 reply; 15+ messages in thread
From: Alan Modra @ 2023-06-06 6:48 UTC (permalink / raw)
To: H.J. Lu; +Cc: binutils, Kaylee Blake
On Mon, Jun 05, 2023 at 08:32:15AM -0700, H.J. Lu wrote:
> Changes in v3:
Looks OK to me, except for some minor issues in 3/7 and 6/7. Please
see replies to those emails. OK to commit with those fixed. No need
to repost.
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 6/7] ld: Add tests for -z nosectionheader and --strip-section-headers
2023-06-05 15:32 ` [PATCH v3 6/7] ld: Add tests for -z nosectionheader and --strip-section-headers H.J. Lu
2023-06-06 6:46 ` Alan Modra
@ 2023-06-06 9:57 ` Florian Weimer
2023-06-06 17:26 ` H.J. Lu
1 sibling, 1 reply; 15+ messages in thread
From: Florian Weimer @ 2023-06-06 9:57 UTC (permalink / raw)
To: H.J. Lu via Binutils; +Cc: H.J. Lu, Alan Modra, Kaylee Blake
* H. J. Lu via Binutils:
> 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.
Should this have a test that -r with -z nosectionheader is an error?
Thanks,
Florian
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 6/7] ld: Add tests for -z nosectionheader and --strip-section-headers
2023-06-06 6:46 ` Alan Modra
@ 2023-06-06 17:26 ` H.J. Lu
0 siblings, 0 replies; 15+ messages in thread
From: H.J. Lu @ 2023-06-06 17:26 UTC (permalink / raw)
To: Alan Modra; +Cc: binutils, Kaylee Blake
On Mon, Jun 5, 2023 at 11:51 PM Alan Modra <amodra@gmail.com> wrote:
>
> On Mon, Jun 05, 2023 at 08:32:21AM -0700, H.J. Lu wrote:
> > + 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)"
>
> Needs a return here, otherwise you might get both a fail and a pass.
WIll fix it.
>
> > + }
> > +
> > + pass "Update pr25617-1a-now-no-sec-hdr.so ($prog_name)"
> > + }
> > +}
> > +
> > +binutils_run_test ""
> > +binutils_run_test objcopy
> > +binutils_run_test strip
>
> --
> Alan Modra
> Australia Development Lab, IBM
--
H.J.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 6/7] ld: Add tests for -z nosectionheader and --strip-section-headers
2023-06-06 9:57 ` Florian Weimer
@ 2023-06-06 17:26 ` H.J. Lu
0 siblings, 0 replies; 15+ messages in thread
From: H.J. Lu @ 2023-06-06 17:26 UTC (permalink / raw)
To: Florian Weimer; +Cc: H.J. Lu via Binutils, Alan Modra, Kaylee Blake
On Tue, Jun 6, 2023 at 2:57 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu via Binutils:
>
> > 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.
>
> Should this have a test that -r with -z nosectionheader is an error?
>
Yes, I will fix in v4.
Thanks.
--
H.J.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 0/7] ELF: Strip section header in ELF objects
2023-06-06 6:48 ` [PATCH v3 0/7] ELF: Strip section header in ELF objects Alan Modra
@ 2023-06-29 17:21 ` H.J. Lu
0 siblings, 0 replies; 15+ messages in thread
From: H.J. Lu @ 2023-06-29 17:21 UTC (permalink / raw)
To: Alan Modra; +Cc: binutils, Kaylee Blake
On Mon, Jun 5, 2023 at 11:48 PM Alan Modra <amodra@gmail.com> wrote:
>
> On Mon, Jun 05, 2023 at 08:32:15AM -0700, H.J. Lu wrote:
> > Changes in v3:
>
> Looks OK to me, except for some minor issues in 3/7 and 6/7. Please
> see replies to those emails. OK to commit with those fixed. No need
> to repost.
>
> --
> Alan Modra
> Australia Development Lab, IBM
I will check in the v4 patch:
https://sourceware.org/pipermail/binutils/2023-June/127780.html
Thanks.
--
H.J.
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2023-06-29 17:21 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-05 15:32 [PATCH v3 0/7] ELF: Strip section header in ELF objects H.J. Lu
2023-06-05 15:32 ` [PATCH v3 1/7] " H.J. Lu
2023-06-05 15:32 ` [PATCH v3 2/7] ELF: Discard non-alloc sections without section header H.J. Lu
2023-06-05 15:32 ` [PATCH v3 3/7] bfd: Improve nm and objdump " H.J. Lu
2023-06-06 6:44 ` Alan Modra
2023-06-05 15:32 ` [PATCH v3 4/7] ld: Add a simple test for -z nosectionheader H.J. Lu
2023-06-05 15:32 ` [PATCH v3 5/7] binutils: Add a --strip-section-headers test H.J. Lu
2023-06-05 15:32 ` [PATCH v3 6/7] ld: Add tests for -z nosectionheader and --strip-section-headers H.J. Lu
2023-06-06 6:46 ` Alan Modra
2023-06-06 17:26 ` H.J. Lu
2023-06-06 9:57 ` Florian Weimer
2023-06-06 17:26 ` H.J. Lu
2023-06-05 15:32 ` [PATCH v3 7/7] ld: Add -z nosectionheader test to bootstrap.exp H.J. Lu
2023-06-06 6:48 ` [PATCH v3 0/7] ELF: Strip section header in ELF objects Alan Modra
2023-06-29 17:21 ` 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).