mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 10:03:47 +08:00
Keep input SHF_GNU_RETAIN sections and strip output SHF_GNU_RETAIN for GNU/FreBSD ELFOSABIs.
2020-12-14 H.J. Lu <hjl.tools@gmail.com> Cary Coutant <ccoutant@gmail.com> elfcpp/ PR gold/27039 * elfcpp.h (SHF): Add SHF_GNU_RETAIN. gold/ PR gold/27039 * layout.cc (Layout::layout): Strip SHF_GNU_RETAIN. * object.cc (Sized_relobj_file::Sized_relobj_file): Initialize osabi_. (Sized_relobj_file::do_layout): Keep SHF_GNU_RETAIN sections for GNU/FreBSD ELFOSABIs. * object.h (Osabi) New class. (Sized_relobj_file): Add osabi() and osabi_. * testsuite/Makefile.am (check_SCRIPTS): Add retain.sh. (check_DATA): Add retain_1.out retain_2.out. (MOSTLYCLEANFILES): Add retain_1 retain_2. (retain_1.out): New target. (retain_1): Likewise. (retain_1.o): Likewise. (retain_2.out): Likewise. (retain_2): Likewise. (retain_2.o): Likewise. * testsuite/Makefile.in: Regenerate. * testsuite/retain.sh: New file. * testsuite/retain_1.s: Likewise. * testsuite/retain_2.s: Likewise.
This commit is contained in:
parent
8cd6d968de
commit
ff4bc37d77
@ -438,6 +438,7 @@ enum SHF
|
||||
SHF_TLS = 0x400,
|
||||
SHF_COMPRESSED = 0x800,
|
||||
SHF_MASKOS = 0x0ff00000,
|
||||
SHF_GNU_RETAIN = 0x200000,
|
||||
SHF_MASKPROC = 0xf0000000,
|
||||
|
||||
// Indicates this section requires ordering in relation to
|
||||
|
@ -1173,14 +1173,20 @@ Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int shndx,
|
||||
{
|
||||
// Some flags in the input section should not be automatically
|
||||
// copied to the output section.
|
||||
elfcpp::Elf_Xword flags = (shdr.get_sh_flags()
|
||||
& ~ elfcpp::SHF_COMPRESSED);
|
||||
elfcpp::Elf_Xword sh_flags = (shdr.get_sh_flags()
|
||||
& ~ elfcpp::SHF_COMPRESSED);
|
||||
name = this->namepool_.add(name, true, NULL);
|
||||
os = this->make_output_section(name, sh_type, flags,
|
||||
ORDER_INVALID, false);
|
||||
os = this->make_output_section(name, sh_type, sh_flags, ORDER_INVALID,
|
||||
false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the section flags and mask out any flags that do not
|
||||
// take part in section matching.
|
||||
elfcpp::Elf_Xword sh_flags
|
||||
= (this->get_output_section_flags(shdr.get_sh_flags())
|
||||
& ~object->osabi().ignored_sh_flags());
|
||||
|
||||
// All ".text.unlikely.*" sections can be moved to a unique
|
||||
// segment with --text-unlikely-segment option.
|
||||
bool text_unlikely_segment
|
||||
@ -1189,13 +1195,10 @@ Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int shndx,
|
||||
object->section_name(shndx).c_str()));
|
||||
if (text_unlikely_segment)
|
||||
{
|
||||
elfcpp::Elf_Xword flags
|
||||
= this->get_output_section_flags(shdr.get_sh_flags());
|
||||
|
||||
Stringpool::Key name_key;
|
||||
const char* os_name = this->namepool_.add(".text.unlikely", true,
|
||||
&name_key);
|
||||
os = this->get_output_section(os_name, name_key, sh_type, flags,
|
||||
os = this->get_output_section(os_name, name_key, sh_type, sh_flags,
|
||||
ORDER_INVALID, false);
|
||||
// Map this output section to a unique segment. This is done to
|
||||
// separate "text" that is not likely to be executed from "text"
|
||||
@ -1213,22 +1216,18 @@ Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int shndx,
|
||||
if (it == this->section_segment_map_.end())
|
||||
{
|
||||
os = this->choose_output_section(object, name, sh_type,
|
||||
shdr.get_sh_flags(), true,
|
||||
ORDER_INVALID, false, false,
|
||||
true);
|
||||
sh_flags, true, ORDER_INVALID,
|
||||
false, false, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We know the name of the output section, directly call
|
||||
// get_output_section here by-passing choose_output_section.
|
||||
elfcpp::Elf_Xword flags
|
||||
= this->get_output_section_flags(shdr.get_sh_flags());
|
||||
|
||||
const char* os_name = it->second->name;
|
||||
Stringpool::Key name_key;
|
||||
os_name = this->namepool_.add(os_name, true, &name_key);
|
||||
os = this->get_output_section(os_name, name_key, sh_type, flags,
|
||||
ORDER_INVALID, false);
|
||||
os = this->get_output_section(os_name, name_key, sh_type,
|
||||
sh_flags, ORDER_INVALID, false);
|
||||
if (!os->is_unique_segment())
|
||||
{
|
||||
os->set_is_unique_segment();
|
||||
|
@ -464,6 +464,7 @@ Sized_relobj_file<size, big_endian>::Sized_relobj_file(
|
||||
const elfcpp::Ehdr<size, big_endian>& ehdr)
|
||||
: Sized_relobj<size, big_endian>(name, input_file, offset),
|
||||
elf_file_(this, ehdr),
|
||||
osabi_(ehdr),
|
||||
symtab_shndx_(-1U),
|
||||
local_symbol_count_(0),
|
||||
output_local_symbol_count_(0),
|
||||
@ -1706,7 +1707,8 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
|
||||
if (this->is_section_name_included(name)
|
||||
|| layout->keep_input_section (this, name)
|
||||
|| sh_type == elfcpp::SHT_INIT_ARRAY
|
||||
|| sh_type == elfcpp::SHT_FINI_ARRAY)
|
||||
|| sh_type == elfcpp::SHT_FINI_ARRAY
|
||||
|| this->osabi().has_shf_retain(shdr.get_sh_flags()))
|
||||
{
|
||||
symtab->gc()->worklist().push_back(Section_id(this, i));
|
||||
}
|
||||
|
@ -384,6 +384,49 @@ build_compressed_section_map(const unsigned char* pshdrs, unsigned int shnum,
|
||||
const char* names, section_size_type names_size,
|
||||
Object* obj, bool decompress_if_needed);
|
||||
|
||||
// Osabi represents the EI_OSABI field from the ELF header.
|
||||
|
||||
template <int size, bool big_endian>
|
||||
class Osabi
|
||||
{
|
||||
public:
|
||||
Osabi(const elfcpp::Ehdr<size, big_endian>& ehdr)
|
||||
: ei_osabi_(static_cast<elfcpp::ELFOSABI>(
|
||||
ehdr.get_e_ident()[elfcpp::EI_OSABI]))
|
||||
{ }
|
||||
|
||||
bool
|
||||
has_shf_retain(elfcpp::Elf_Xword sh_flags) const
|
||||
{
|
||||
switch (this->ei_osabi_)
|
||||
{
|
||||
case elfcpp::ELFOSABI_GNU:
|
||||
case elfcpp::ELFOSABI_FREEBSD:
|
||||
return (sh_flags & elfcpp::SHF_GNU_RETAIN) != 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
elfcpp::Elf_Xword
|
||||
ignored_sh_flags() const
|
||||
{
|
||||
switch (this->ei_osabi_)
|
||||
{
|
||||
case elfcpp::ELFOSABI_GNU:
|
||||
case elfcpp::ELFOSABI_FREEBSD:
|
||||
return elfcpp::SHF_GNU_RETAIN;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
elfcpp::ELFOSABI ei_osabi_;
|
||||
};
|
||||
|
||||
// Object is an abstract base class which represents either a 32-bit
|
||||
// or a 64-bit input object. This can be a regular object file
|
||||
// (ET_REL) or a shared object (ET_DYN).
|
||||
@ -2205,6 +2248,11 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
|
||||
e_type() const
|
||||
{ return this->e_type_; }
|
||||
|
||||
// Return the EI_OSABI.
|
||||
const Osabi<size, big_endian>&
|
||||
osabi() const
|
||||
{ return this->osabi_; }
|
||||
|
||||
// Return the number of symbols. This is only valid after
|
||||
// Object::add_symbols has been called.
|
||||
unsigned int
|
||||
@ -2845,6 +2893,8 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
|
||||
|
||||
// General access to the ELF file.
|
||||
elfcpp::Elf_file<size, big_endian, Object> elf_file_;
|
||||
// The EI_OSABI.
|
||||
const Osabi<size, big_endian> osabi_;
|
||||
// Type of ELF file (ET_REL or ET_EXEC). ET_EXEC files are allowed
|
||||
// as input files only for the --just-symbols option.
|
||||
int e_type_;
|
||||
|
@ -4418,4 +4418,20 @@ pr26936c.o: pr26936c.s
|
||||
pr26936d.o: pr26936d.s
|
||||
$(TEST_AS) --gen-debug -mx86-used-note=yes -o $@ $<
|
||||
|
||||
check_SCRIPTS += retain.sh
|
||||
check_DATA += retain_1.out retain_2.out
|
||||
MOSTLYCLEANFILES += retain_1 retain_2
|
||||
retain_1.out: retain_1
|
||||
$(TEST_NM) $< >$@
|
||||
retain_1: retain_1.o ../ld-new
|
||||
../ld-new -e _start --gc-sections -o $@ retain_1.o
|
||||
retain_1.o: retain_1.s
|
||||
$(TEST_AS) -o $@ $<
|
||||
retain_2.out: retain_2
|
||||
$(TEST_READELF) -d $< >$@
|
||||
retain_2: retain_2.o ../ld-new
|
||||
../ld-new -pie -e _start --gc-sections -o $@ retain_2.o
|
||||
retain_2.o: retain_2.s
|
||||
$(TEST_AS) -o $@ $<
|
||||
|
||||
endif DEFAULT_TARGET_X86_64
|
||||
|
@ -1130,12 +1130,13 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
|
||||
@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ split_s390x_z4_ns split_s390x_n1_ns split_s390x_n2_ns split_s390x_r
|
||||
|
||||
@DEFAULT_TARGET_X86_64_TRUE@am__append_114 = *.dwo *.dwp pr26936a \
|
||||
@DEFAULT_TARGET_X86_64_TRUE@ pr26936b
|
||||
@DEFAULT_TARGET_X86_64_TRUE@ pr26936b retain_1 retain_2
|
||||
@DEFAULT_TARGET_X86_64_TRUE@am__append_115 = dwp_test_1.sh \
|
||||
@DEFAULT_TARGET_X86_64_TRUE@ dwp_test_2.sh pr26936.sh
|
||||
@DEFAULT_TARGET_X86_64_TRUE@ dwp_test_2.sh pr26936.sh retain.sh
|
||||
@DEFAULT_TARGET_X86_64_TRUE@am__append_116 = dwp_test_1.stdout \
|
||||
@DEFAULT_TARGET_X86_64_TRUE@ dwp_test_2.stdout pr26936a.stdout \
|
||||
@DEFAULT_TARGET_X86_64_TRUE@ pr26936b.stdout
|
||||
@DEFAULT_TARGET_X86_64_TRUE@ pr26936b.stdout retain_1.out \
|
||||
@DEFAULT_TARGET_X86_64_TRUE@ retain_2.out
|
||||
subdir = testsuite
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/../config/ax_pthread.m4 \
|
||||
@ -6451,6 +6452,13 @@ pr26936.sh.log: pr26936.sh
|
||||
--log-file $$b.log --trs-file $$b.trs \
|
||||
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
|
||||
"$$tst" $(AM_TESTS_FD_REDIRECT)
|
||||
retain.sh.log: retain.sh
|
||||
@p='retain.sh'; \
|
||||
b='retain.sh'; \
|
||||
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
|
||||
--log-file $$b.log --trs-file $$b.trs \
|
||||
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
|
||||
"$$tst" $(AM_TESTS_FD_REDIRECT)
|
||||
object_unittest.log: object_unittest$(EXEEXT)
|
||||
@p='object_unittest$(EXEEXT)'; \
|
||||
b='object_unittest'; \
|
||||
@ -10394,6 +10402,18 @@ uninstall-am:
|
||||
@DEFAULT_TARGET_X86_64_TRUE@ $(TEST_AS) --gen-debug -mx86-used-note=yes -o $@ $<
|
||||
@DEFAULT_TARGET_X86_64_TRUE@pr26936d.o: pr26936d.s
|
||||
@DEFAULT_TARGET_X86_64_TRUE@ $(TEST_AS) --gen-debug -mx86-used-note=yes -o $@ $<
|
||||
@DEFAULT_TARGET_X86_64_TRUE@retain_1.out: retain_1
|
||||
@DEFAULT_TARGET_X86_64_TRUE@ $(TEST_NM) $< >$@
|
||||
@DEFAULT_TARGET_X86_64_TRUE@retain_1: retain_1.o ../ld-new
|
||||
@DEFAULT_TARGET_X86_64_TRUE@ ../ld-new -e _start --gc-sections -o $@ retain_1.o
|
||||
@DEFAULT_TARGET_X86_64_TRUE@retain_1.o: retain_1.s
|
||||
@DEFAULT_TARGET_X86_64_TRUE@ $(TEST_AS) -o $@ $<
|
||||
@DEFAULT_TARGET_X86_64_TRUE@retain_2.out: retain_2
|
||||
@DEFAULT_TARGET_X86_64_TRUE@ $(TEST_READELF) -d $< >$@
|
||||
@DEFAULT_TARGET_X86_64_TRUE@retain_2: retain_2.o ../ld-new
|
||||
@DEFAULT_TARGET_X86_64_TRUE@ ../ld-new -pie -e _start --gc-sections -o $@ retain_2.o
|
||||
@DEFAULT_TARGET_X86_64_TRUE@retain_2.o: retain_2.s
|
||||
@DEFAULT_TARGET_X86_64_TRUE@ $(TEST_AS) -o $@ $<
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
|
60
gold/testsuite/retain.sh
Executable file
60
gold/testsuite/retain.sh
Executable file
@ -0,0 +1,60 @@
|
||||
#!/bin/sh
|
||||
|
||||
# retain.sh -- Tests for SHF_GNU_RETAIN.
|
||||
|
||||
# Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
|
||||
# This file is part of gold.
|
||||
|
||||
# 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.
|
||||
|
||||
set -e
|
||||
|
||||
check()
|
||||
{
|
||||
number_of_occurrence=`egrep "$2" ./$1 -o | wc -l`
|
||||
if [ $number_of_occurrence != $3 ]
|
||||
then
|
||||
echo "$1: \"$2\" $3: Failed"
|
||||
status=1
|
||||
fi
|
||||
}
|
||||
|
||||
status=0
|
||||
check retain_1.out " T fnretain1" 1
|
||||
check retain_1.out " b lsretain0.2" 1
|
||||
check retain_1.out " b lsretain1.1" 1
|
||||
check retain_1.out " d lsretain2.0" 1
|
||||
check retain_1.out " B retain0" 1
|
||||
check retain_1.out " B retain1" 1
|
||||
check retain_1.out " D retain2" 1
|
||||
check retain_1.out " b sretain0" 1
|
||||
check retain_1.out " b sretain1" 1
|
||||
check retain_1.out " d sretain2" 1
|
||||
if grep discard retain_1.out
|
||||
then
|
||||
echo "retain_1.out: Garbage collection failed"
|
||||
status=1
|
||||
fi
|
||||
|
||||
check retain_2.out " \(PREINIT_ARRAY\)" 1
|
||||
check retain_2.out " \(PREINIT_ARRAYSZ\)" 1
|
||||
check retain_2.out " \(INIT_ARRAY\)" 1
|
||||
check retain_2.out " \(INIT_ARRAYSZ\)" 1
|
||||
check retain_2.out " \(FINI_ARRAY\)" 1
|
||||
check retain_2.out " \(FINI_ARRAYSZ\)" 1
|
||||
|
||||
exit $status
|
104
gold/testsuite/retain_1.s
Normal file
104
gold/testsuite/retain_1.s
Normal file
@ -0,0 +1,104 @@
|
||||
.global discard0
|
||||
.section .bss.discard0,"aw"
|
||||
.type discard0, %object
|
||||
discard0:
|
||||
.zero 2
|
||||
|
||||
.global discard1
|
||||
.section .bss.discard1,"aw"
|
||||
.type discard1, %object
|
||||
discard1:
|
||||
.zero 2
|
||||
|
||||
.global discard2
|
||||
.section .data.discard2,"aw"
|
||||
.type discard2, %object
|
||||
discard2:
|
||||
.word 1
|
||||
|
||||
.section .bss.sdiscard0,"aw"
|
||||
.type sdiscard0, %object
|
||||
sdiscard0:
|
||||
.zero 2
|
||||
|
||||
.section .bss.sdiscard1,"aw"
|
||||
.type sdiscard1, %object
|
||||
sdiscard1:
|
||||
.zero 2
|
||||
|
||||
.section .data.sdiscard2,"aw"
|
||||
.type sdiscard2, %object
|
||||
sdiscard2:
|
||||
.word 1
|
||||
|
||||
.section .text.fndiscard0,"ax"
|
||||
.global fndiscard0
|
||||
.type fndiscard0, %function
|
||||
fndiscard0:
|
||||
.word 0
|
||||
|
||||
.global retain0
|
||||
.section .bss.retain0,"awR"
|
||||
.type retain0, %object
|
||||
retain0:
|
||||
.zero 2
|
||||
|
||||
.global retain1
|
||||
.section .bss.retain1,"awR"
|
||||
.type retain1, %object
|
||||
retain1:
|
||||
.zero 2
|
||||
|
||||
.global retain2
|
||||
.section .data.retain2,"awR"
|
||||
.type retain2, %object
|
||||
retain2:
|
||||
.word 1
|
||||
|
||||
.section .bss.sretain0,"awR"
|
||||
.type sretain0, %object
|
||||
sretain0:
|
||||
.zero 2
|
||||
|
||||
.section .bss.sretain1,"awR"
|
||||
.type sretain1, %object
|
||||
sretain1:
|
||||
.zero 2
|
||||
|
||||
.section .data.sretain2,"aRw"
|
||||
.type sretain2, %object
|
||||
sretain2:
|
||||
.word 1
|
||||
|
||||
.section .text.fnretain1,"Rax"
|
||||
.global fnretain1
|
||||
.type fnretain1, %function
|
||||
fnretain1:
|
||||
.word 0
|
||||
|
||||
.section .text.fndiscard2,"ax"
|
||||
.global fndiscard2
|
||||
.type fndiscard2, %function
|
||||
fndiscard2:
|
||||
.word 0
|
||||
|
||||
.section .bss.lsretain0,"awR"
|
||||
.type lsretain0.2, %object
|
||||
lsretain0.2:
|
||||
.zero 2
|
||||
|
||||
.section .bss.lsretain1,"aRw"
|
||||
.type lsretain1.1, %object
|
||||
lsretain1.1:
|
||||
.zero 2
|
||||
|
||||
.section .data.lsretain2,"aRw"
|
||||
.type lsretain2.0, %object
|
||||
lsretain2.0:
|
||||
.word 1
|
||||
|
||||
.section .text._start,"ax"
|
||||
.global _start
|
||||
.type _start, %function
|
||||
_start:
|
||||
.word 0
|
22
gold/testsuite/retain_2.s
Normal file
22
gold/testsuite/retain_2.s
Normal file
@ -0,0 +1,22 @@
|
||||
.section .preinit_array.01000,"aw",%preinit_array
|
||||
.dc.a 0
|
||||
|
||||
.section .init_array.01000,"aw",%init_array
|
||||
.dc.a 0
|
||||
|
||||
.section .fini_array.01000,"aw",%fini_array
|
||||
.dc.a 0
|
||||
|
||||
.section .preinit_array.01000,"awR",%preinit_array
|
||||
.dc.a 0
|
||||
|
||||
.section .init_array.01000,"awR",%init_array
|
||||
.dc.a 0
|
||||
|
||||
.section .fini_array.01000,"awR",%fini_array
|
||||
.dc.a 0
|
||||
|
||||
.text
|
||||
.globl _start
|
||||
_start:
|
||||
.dc.a 0
|
Loading…
Reference in New Issue
Block a user