This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH 2/7] Fix --gc-sections for C++ MIPS ELF
- From: Richard Sandiford <rsandifo at nildram dot co dot uk>
- To: binutils at sourceware dot org
- Date: Sun, 02 Dec 2007 20:19:14 +0000
- Subject: [PATCH 2/7] Fix --gc-sections for C++ MIPS ELF
- References: <87r6i4svjg.fsf@firetop.home>
Later patches want to know the index of the first relocation against
a particular FDE or CIE, so this patch adds a reloc_index field to
eh_cie_fde. We currently have:
struct eh_cie_fde *cie_inf;
unsigned int size;
unsigned int offset;
unsigned int new_offset;
unsigned char fde_encoding;
unsigned char lsda_encoding;
unsigned char lsda_offset;
unsigned int cie : 1;
unsigned int removed : 1;
unsigned int add_augmentation_size : 1;
unsigned int add_fde_encoding : 1;
unsigned int make_relative : 1;
unsigned int make_lsda_relative : 1;
unsigned int need_lsda_relative : 1;
unsigned int per_encoding_relative : 1;
unsigned int *set_loc;
i.e. 3 unsigned chars and 8 bits in an unsigned int, so we can
avoid growing the structure by turning the "unsigned char"s into
"unsigned int : 8"s.
Also, later patches want to add some CIE-specific information,
so this patch puts the FDE-specific cie_inf in a union.
Richard
bfd/
* elf-bfd.h (eh_cie_fde): Put cie_inf in a union. Add a reloc_index
field. Use bitfields for fde_encoding, lsda_encoding and lsda_offset.
* elf-eh-frame.c (extra_augmentation_data_bytes): Adjust cie_inf
accesses after the above change.
(_bfd_elf_eh_frame_section_offset): Likewise.
(_bfd_elf_write_section_eh_frame): Likewise.
(_bfd_elf_discard_section_eh_frame): Likewise. Set up reloc_index.
Index: bfd/elf-bfd.h
===================================================================
--- bfd/elf-bfd.h 2007-12-02 16:59:46.000000000 +0000
+++ bfd/elf-bfd.h 2007-12-02 17:01:08.000000000 +0000
@@ -264,14 +264,19 @@ struct elf_link_loaded_list
/* Structures used by the eh_frame optimization code. */
struct eh_cie_fde
{
- /* For FDEs, this points to the CIE used. */
- struct eh_cie_fde *cie_inf;
+ union {
+ struct {
+ /* The CIE that we have chosen to use for this FDE. */
+ struct eh_cie_fde *cie_inf;
+ } fde;
+ } u;
+ unsigned int reloc_index;
unsigned int size;
unsigned int offset;
unsigned int new_offset;
- unsigned char fde_encoding;
- unsigned char lsda_encoding;
- unsigned char lsda_offset;
+ unsigned int fde_encoding : 8;
+ unsigned int lsda_encoding : 8;
+ unsigned int lsda_offset : 8;
unsigned int cie : 1;
unsigned int removed : 1;
unsigned int add_augmentation_size : 1;
Index: bfd/elf-eh-frame.c
===================================================================
--- bfd/elf-eh-frame.c 2007-12-02 16:59:44.000000000 +0000
+++ bfd/elf-eh-frame.c 2007-12-02 17:01:08.000000000 +0000
@@ -304,7 +304,7 @@ extra_augmentation_data_bytes (struct eh
}
else
{
- if (entry->cie_inf->add_augmentation_size)
+ if (entry->u.fde.cie_inf->add_augmentation_size)
size++;
}
return size;
@@ -572,6 +572,7 @@ #define GET_RELOC(buf) \
this_inf->offset = last_fde - ehbuf;
this_inf->size = 4 + hdr_length;
+ this_inf->reloc_index = cookie->rel - cookie->rels;
if (hdr_length == 0)
{
@@ -826,7 +827,7 @@ #define GET_RELOC(buf) \
}
ecie->usage_count++;
hdr_info->fde_count++;
- this_inf->cie_inf = (void *) (ecie - ecies);
+ this_inf->u.fde.cie_inf = (void *) (ecie - ecies);
}
/* Skip the initial location and address range. */
@@ -954,8 +955,8 @@ #define GET_RELOC(buf) \
{
if (!ent->cie)
{
- ecie = ecies + (bfd_hostptr_t) ent->cie_inf;
- ent->cie_inf = ecie->cie.cie_inf;
+ ecie = ecies + (bfd_hostptr_t) ent->u.fde.cie_inf;
+ ent->u.fde.cie_inf = ecie->cie.cie_inf;
}
ent->new_offset = offset;
offset += size_of_output_cie_fde (ent, ptr_size);
@@ -1116,20 +1117,20 @@ _bfd_elf_eh_frame_section_offset (bfd *o
/* If converting to DW_EH_PE_pcrel, there will be no need for run-time
relocation against FDE's initial_location field. */
if (!sec_info->entry[mid].cie
- && sec_info->entry[mid].cie_inf->make_relative
+ && sec_info->entry[mid].u.fde.cie_inf->make_relative
&& offset == sec_info->entry[mid].offset + 8)
return (bfd_vma) -2;
/* If converting LSDA pointers to DW_EH_PE_pcrel, there will be no need
for run-time relocation against LSDA field. */
if (!sec_info->entry[mid].cie
- && sec_info->entry[mid].cie_inf->make_lsda_relative
+ && sec_info->entry[mid].u.fde.cie_inf->make_lsda_relative
&& (offset == (sec_info->entry[mid].offset + 8
+ sec_info->entry[mid].lsda_offset))
- && (sec_info->entry[mid].cie_inf->need_lsda_relative
+ && (sec_info->entry[mid].u.fde.cie_inf->need_lsda_relative
|| !hdr_info->offsets_adjusted))
{
- sec_info->entry[mid].cie_inf->need_lsda_relative = 1;
+ sec_info->entry[mid].u.fde.cie_inf->need_lsda_relative = 1;
return (bfd_vma) -2;
}
@@ -1138,7 +1139,7 @@ _bfd_elf_eh_frame_section_offset (bfd *o
if (sec_info->entry[mid].set_loc
&& (sec_info->entry[mid].cie
? sec_info->entry[mid].make_relative
- : sec_info->entry[mid].cie_inf->make_relative)
+ : sec_info->entry[mid].u.fde.cie_inf->make_relative)
&& (offset >= sec_info->entry[mid].offset + 8
+ sec_info->entry[mid].set_loc[1]))
{
@@ -1375,10 +1376,12 @@ _bfd_elf_write_section_eh_frame (bfd *ab
bfd_vma value, address;
unsigned int width;
bfd_byte *start;
+ struct eh_cie_fde *cie;
/* Skip length. */
+ cie = ent->u.fde.cie_inf;
buf += 4;
- value = ent->new_offset + 4 - ent->cie_inf->new_offset;
+ value = ent->new_offset + 4 - cie->new_offset;
bfd_put_32 (abfd, value, buf);
buf += 4;
width = get_DW_EH_PE_width (ent->fde_encoding, ptr_size);
@@ -1406,7 +1409,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab
address += sec->output_section->vma + ent->offset + 8;
break;
}
- if (ent->cie_inf->make_relative)
+ if (cie->make_relative)
value -= sec->output_section->vma + ent->new_offset + 8;
write_value (abfd, buf, value, width);
}
@@ -1421,7 +1424,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab
}
if ((ent->lsda_encoding & 0xf0) == DW_EH_PE_pcrel
- || ent->cie_inf->need_lsda_relative)
+ || cie->need_lsda_relative)
{
buf += ent->lsda_offset;
width = get_DW_EH_PE_width (ent->lsda_encoding, ptr_size);
@@ -1431,13 +1434,13 @@ _bfd_elf_write_section_eh_frame (bfd *ab
{
if ((ent->lsda_encoding & 0xf0) == DW_EH_PE_pcrel)
value += ent->offset - ent->new_offset;
- else if (ent->cie_inf->need_lsda_relative)
+ else if (cie->need_lsda_relative)
value -= (sec->output_section->vma + ent->new_offset + 8
+ ent->lsda_offset);
write_value (abfd, buf, value, width);
}
}
- else if (ent->cie_inf->add_augmentation_size)
+ else if (cie->add_augmentation_size)
{
/* Skip the PC and length and insert a zero byte for the
augmentation size. */
@@ -1469,7 +1472,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab
if ((ent->fde_encoding & 0xf0) == DW_EH_PE_pcrel)
value += ent->offset + 8 - new_offset;
- if (ent->cie_inf->make_relative)
+ if (cie->make_relative)
value -= sec->output_section->vma + new_offset
+ ent->set_loc[cnt];
write_value (abfd, buf, value, width);