* elf.c (setup_group): Set SEC_LINK_ONCE on GRP_COMDAT groups.
(bfd_section_from_shdr): Likewise. Set section name of group sections from signature. (group_signature): Split out from setup_group. Ensure symbol table is available. (bfd_elf_discard_group): New function. (_bfd_elf_make_section_from_shdr): Don't set SEC_LINK_ONCE on .gnu.linkonce* sections if they are members of a group. (set_group_contents): Set GRP_COMDAT flag. * section.c (bfd_discard_group): New function. * bfd-in.h (bfd_elf_discard_group): Declare. * bfd-in2.h: Regenerate. * elf-bfd.h (struct bfd_elf_section_data): Add linkonce_p field. (elf_linkonce_p): Define.
This commit is contained in:
parent
90937f86aa
commit
b885599bed
6 changed files with 117 additions and 19 deletions
|
@ -1,3 +1,20 @@
|
|||
2002-06-04 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* elf.c (setup_group): Set SEC_LINK_ONCE on GRP_COMDAT groups.
|
||||
(bfd_section_from_shdr): Likewise. Set section name of group
|
||||
sections from signature.
|
||||
(group_signature): Split out from setup_group. Ensure symbol table
|
||||
is available.
|
||||
(bfd_elf_discard_group): New function.
|
||||
(_bfd_elf_make_section_from_shdr): Don't set SEC_LINK_ONCE on
|
||||
.gnu.linkonce* sections if they are members of a group.
|
||||
(set_group_contents): Set GRP_COMDAT flag.
|
||||
* section.c (bfd_discard_group): New function.
|
||||
* bfd-in.h (bfd_elf_discard_group): Declare.
|
||||
* bfd-in2.h: Regenerate.
|
||||
* elf-bfd.h (struct bfd_elf_section_data): Add linkonce_p field.
|
||||
(elf_linkonce_p): Define.
|
||||
|
||||
2002-06-04 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* elf.c (bfd_section_from_shdr): Make "name" const.
|
||||
|
|
|
@ -657,6 +657,8 @@ extern boolean bfd_elf32_discard_info
|
|||
PARAMS ((bfd *, struct bfd_link_info *));
|
||||
extern boolean bfd_elf64_discard_info
|
||||
PARAMS ((bfd *, struct bfd_link_info *));
|
||||
extern void bfd_elf_discard_group
|
||||
PARAMS ((bfd *, struct sec *));
|
||||
|
||||
/* Return an upper bound on the number of bytes required to store a
|
||||
copy of ABFD's program header table entries. Return -1 if an error
|
||||
|
|
|
@ -663,6 +663,8 @@ extern boolean bfd_elf32_discard_info
|
|||
PARAMS ((bfd *, struct bfd_link_info *));
|
||||
extern boolean bfd_elf64_discard_info
|
||||
PARAMS ((bfd *, struct bfd_link_info *));
|
||||
extern void bfd_elf_discard_group
|
||||
PARAMS ((bfd *, struct sec *));
|
||||
|
||||
/* Return an upper bound on the number of bytes required to store a
|
||||
copy of ABFD's program header table entries. Return -1 if an error
|
||||
|
@ -1450,6 +1452,9 @@ bfd_copy_private_section_data PARAMS ((bfd *ibfd, asection *isec,
|
|||
void
|
||||
_bfd_strip_section_from_output PARAMS ((struct bfd_link_info *info, asection *section));
|
||||
|
||||
void
|
||||
bfd_discard_group PARAMS ((bfd *abfd, asection *group));
|
||||
|
||||
enum bfd_architecture
|
||||
{
|
||||
bfd_arch_unknown, /* File arch not known. */
|
||||
|
|
|
@ -926,11 +926,15 @@ struct bfd_elf_section_data
|
|||
|
||||
/* Nonzero if this section uses RELA relocations, rather than REL. */
|
||||
unsigned int use_rela_p:1;
|
||||
|
||||
/* Nonzero when a group is COMDAT. */
|
||||
unsigned int linkonce_p:1;
|
||||
};
|
||||
|
||||
#define elf_section_data(sec) ((struct bfd_elf_section_data*)sec->used_by_bfd)
|
||||
#define elf_group_name(sec) (elf_section_data(sec)->group_name)
|
||||
#define elf_next_in_group(sec) (elf_section_data(sec)->next_in_group)
|
||||
#define elf_linkonce_p(sec) (elf_section_data(sec)->linkonce_p)
|
||||
|
||||
/* Return true if section has been discarded. */
|
||||
#define elf_discarded_section(sec) \
|
||||
|
|
87
bfd/elf.c
87
bfd/elf.c
|
@ -50,6 +50,7 @@ static boolean prep_headers PARAMS ((bfd *));
|
|||
static boolean swap_out_syms PARAMS ((bfd *, struct bfd_strtab_hash **, int));
|
||||
static boolean copy_private_bfd_data PARAMS ((bfd *, bfd *));
|
||||
static char *elf_read PARAMS ((bfd *, file_ptr, bfd_size_type));
|
||||
static const char *group_signature PARAMS ((bfd *, Elf_Internal_Shdr *));
|
||||
static boolean setup_group PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
|
||||
static void merge_sections_remove_hook PARAMS ((bfd *, asection *));
|
||||
static void elf_fake_sections PARAMS ((bfd *, asection *, PTR));
|
||||
|
@ -361,6 +362,35 @@ typedef union elf_internal_group {
|
|||
unsigned int flags;
|
||||
} Elf_Internal_Group;
|
||||
|
||||
/* Return the name of the group signature symbol. Why isn't the
|
||||
signature just a string? */
|
||||
|
||||
static const char *
|
||||
group_signature (abfd, ghdr)
|
||||
bfd *abfd;
|
||||
Elf_Internal_Shdr *ghdr;
|
||||
{
|
||||
struct elf_backend_data *bed;
|
||||
file_ptr pos;
|
||||
unsigned char ename[4];
|
||||
unsigned long iname;
|
||||
|
||||
/* First we need to ensure the symbol table is available. */
|
||||
if (! bfd_section_from_shdr (abfd, ghdr->sh_link))
|
||||
return NULL;
|
||||
|
||||
/* Fortunately, the name index is at the same place in the external
|
||||
symbol for both 32 and 64 bit ELF. */
|
||||
bed = get_elf_backend_data (abfd);
|
||||
pos = elf_tdata (abfd)->symtab_hdr.sh_offset;
|
||||
pos += ghdr->sh_info * bed->s->sizeof_sym;
|
||||
if (bfd_seek (abfd, pos, SEEK_SET) != 0
|
||||
|| bfd_bread (ename, (bfd_size_type) 4, abfd) != 4)
|
||||
return NULL;
|
||||
iname = H_GET_32 (abfd, ename);
|
||||
return elf_string_from_elf_strtab (abfd, iname);
|
||||
}
|
||||
|
||||
/* Set next_in_group list pointer, and group name for NEWSECT. */
|
||||
|
||||
static boolean
|
||||
|
@ -440,6 +470,9 @@ setup_group (abfd, hdr, newsect)
|
|||
if (src == shdr->contents)
|
||||
{
|
||||
dest->flags = idx;
|
||||
if (shdr->bfd_section != NULL && (idx & GRP_COMDAT))
|
||||
shdr->bfd_section->flags
|
||||
|= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
|
||||
break;
|
||||
}
|
||||
if (idx >= shnum)
|
||||
|
@ -492,32 +525,20 @@ setup_group (abfd, hdr, newsect)
|
|||
}
|
||||
else
|
||||
{
|
||||
struct elf_backend_data *bed;
|
||||
file_ptr pos;
|
||||
unsigned char ename[4];
|
||||
unsigned long iname;
|
||||
const char *gname;
|
||||
|
||||
/* Humbug. Get the name from the group signature
|
||||
symbol. Why isn't the signature just a string?
|
||||
Fortunately, the name index is at the same
|
||||
place in the external symbol for both 32 and 64
|
||||
bit ELF. */
|
||||
bed = get_elf_backend_data (abfd);
|
||||
pos = elf_tdata (abfd)->symtab_hdr.sh_offset;
|
||||
pos += shdr->sh_info * bed->s->sizeof_sym;
|
||||
if (bfd_seek (abfd, pos, SEEK_SET) != 0
|
||||
|| bfd_bread (ename, (bfd_size_type) 4, abfd) != 4)
|
||||
gname = group_signature (abfd, shdr);
|
||||
if (gname == NULL)
|
||||
return false;
|
||||
iname = H_GET_32 (abfd, ename);
|
||||
gname = elf_string_from_elf_strtab (abfd, iname);
|
||||
elf_group_name (newsect) = gname;
|
||||
|
||||
/* Start a circular list with one element. */
|
||||
elf_next_in_group (newsect) = newsect;
|
||||
}
|
||||
|
||||
if (shdr->bfd_section != NULL)
|
||||
elf_next_in_group (shdr->bfd_section) = newsect;
|
||||
|
||||
i = num_group - 1;
|
||||
break;
|
||||
}
|
||||
|
@ -532,6 +553,24 @@ setup_group (abfd, hdr, newsect)
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
bfd_elf_discard_group (abfd, group)
|
||||
bfd *abfd ATTRIBUTE_UNUSED;
|
||||
asection *group;
|
||||
{
|
||||
asection *first = elf_next_in_group (group);
|
||||
asection *s = first;
|
||||
|
||||
while (s != NULL)
|
||||
{
|
||||
s->output_section = bfd_abs_section_ptr;
|
||||
s = elf_next_in_group (s);
|
||||
/* These lists are circular. */
|
||||
if (s == first)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make a BFD section from an ELF section. We store a pointer to the
|
||||
BFD section in the bfd_section field of the header. */
|
||||
|
||||
|
@ -620,7 +659,8 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
|
|||
The symbols will be defined as weak, so that multiple definitions
|
||||
are permitted. The GNU linker extension is to actually discard
|
||||
all but one of the sections. */
|
||||
if (strncmp (name, ".gnu.linkonce", sizeof ".gnu.linkonce" - 1) == 0)
|
||||
if (strncmp (name, ".gnu.linkonce", sizeof ".gnu.linkonce" - 1) == 0
|
||||
&& elf_next_in_group (newsect) == NULL)
|
||||
flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
|
||||
|
||||
bed = get_elf_backend_data (abfd);
|
||||
|
@ -1820,7 +1860,12 @@ bfd_section_from_shdr (abfd, shindex)
|
|||
return true;
|
||||
|
||||
case SHT_GROUP:
|
||||
/* Make a section for objcopy and relocatable links. */
|
||||
/* We need a BFD section for objcopy and relocatable linking,
|
||||
and it's handy to have the signature available as the section
|
||||
name. */
|
||||
name = group_signature (abfd, hdr);
|
||||
if (name == NULL)
|
||||
return false;
|
||||
if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name))
|
||||
return false;
|
||||
if (hdr->contents != NULL)
|
||||
|
@ -1829,6 +1874,10 @@ bfd_section_from_shdr (abfd, shindex)
|
|||
unsigned int n_elt = hdr->sh_size / 4;
|
||||
asection *s;
|
||||
|
||||
if (idx->flags & GRP_COMDAT)
|
||||
hdr->bfd_section->flags
|
||||
|= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
|
||||
|
||||
while (--n_elt != 0)
|
||||
if ((s = (++idx)->shdr->bfd_section) != NULL
|
||||
&& elf_next_in_group (s) != NULL)
|
||||
|
@ -2369,7 +2418,7 @@ set_group_contents (abfd, sec, failedptrarg)
|
|||
while (elt != elf_next_in_group (l->u.indirect.section));
|
||||
|
||||
loc -= 4;
|
||||
H_PUT_32 (abfd, 0, loc);
|
||||
H_PUT_32 (abfd, sec->flags & SEC_LINK_ONCE ? GRP_COMDAT : 0, loc);
|
||||
|
||||
BFD_ASSERT (loc == sec->contents);
|
||||
}
|
||||
|
|
|
@ -1375,3 +1375,24 @@ _bfd_strip_section_from_output (info, s)
|
|||
|
||||
s->flags |= SEC_EXCLUDE;
|
||||
}
|
||||
|
||||
/*
|
||||
FUNCTION
|
||||
bfd_discard_group
|
||||
|
||||
SYNOPSIS
|
||||
void bfd_discard_group (bfd *abfd, asection *group);
|
||||
|
||||
DESCRIPTION
|
||||
Remove all members of @var{group} from the output.
|
||||
*/
|
||||
|
||||
void
|
||||
bfd_discard_group (abfd, group)
|
||||
bfd *abfd;
|
||||
asection *group;
|
||||
{
|
||||
if ((group->flags & SEC_GROUP) != 0
|
||||
&& abfd->xvec->flavour == bfd_target_elf_flavour)
|
||||
bfd_elf_discard_group (abfd, group);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue