This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH 5/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:34:49 +0000
- Subject: [PATCH 5/7] Fix --gc-sections for C++ MIPS ELF
- References: <87r6i4svjg.fsf@firetop.home>
This patch and the next one reorganise eh_cie_fde so that the CIE-specific
flags are in the new u.cie structure. I've split them up because this
first one is more involved, and it's quite likely I'm missing something.
(It's also a prerequisite for removing offsets_adjusted, because I'm
getting rid of one of the checks here.)
We currently have two flags: make_lsda_relative, which says that we
can make LSDA relocations relative if want to, and need_lsda_relative,
which says that we've decided to do that. We need two fields in case
the LSDA is not a pointer:
http://sourceware.org/ml/binutils/2004-09/msg00313.html
We set need_lsda_relative based on make_lsda_relative in
_bfd_elf_eh_frame_section_offset, but could we do it when
parsing the section instead? The original patch linked
above used a make/need_* pair for make_relative as well as
make_lsda_relative, whereas we've now dropped need_relative.
This is now the only case where _bfd_elf_eh_frame_section_offset
changes the CIE and FDE information.
Richard
bfd/
* elf-bfd.h (eh_cie_fde): Remove need_lsda_relative.
Move make_lsda_relative to u.cie.
* elf-eh-frame.c (cie): Rename make_lsda_relative to
can_make_lsda_relative.
(_bfd_elf_parse_eh_frame): Don't set the old eh_cie_fde
make_lsda_relative field. Update after cie renaming.
Set u.cie.make_lsda_relative if can_make_lsda_relative
and if we find a relocation against the LSDA.
(_bfd_elf_discard_section_eh_frame): Copy make_lsda_relative when
changing a CIE's group representative.
(_bfd_elf_eh_frame_section_offset): Don't set need_ldsa_relative here.
(_bfd_elf_write_section_eh_frame): Check u.cie.make_lsda_relative
rather than need_lsda_relative.
Index: bfd/elf-bfd.h
===================================================================
--- bfd/elf-bfd.h 2007-12-02 17:22:22.000000000 +0000
+++ bfd/elf-bfd.h 2007-12-02 17:40:41.000000000 +0000
@@ -285,6 +285,11 @@ struct eh_cie_fde
/* True if we have marked relocations associated with this CIE. */
unsigned int gc_mark : 1;
+
+ /* True if we have decided to turn an absolute LSDA encoding into
+ a PC-relative one. It is the group representative's setting
+ that matters. */
+ unsigned int make_lsda_relative : 1;
} cie;
} u;
unsigned int reloc_index;
@@ -299,8 +304,6 @@ struct eh_cie_fde
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;
};
Index: bfd/elf-eh-frame.c
===================================================================
--- bfd/elf-eh-frame.c 2007-12-02 17:26:13.000000000 +0000
+++ bfd/elf-eh-frame.c 2007-12-02 17:41:29.000000000 +0000
@@ -50,7 +50,7 @@ struct cie
unsigned char fde_encoding;
unsigned char initial_insn_length;
unsigned char make_relative;
- unsigned char make_lsda_relative;
+ unsigned char can_make_lsda_relative;
unsigned char initial_instructions[50];
};
@@ -799,7 +799,7 @@ #define GET_RELOC(buf) \
->elf_backend_can_make_lsda_relative_eh_frame
(abfd, info, sec))
&& (cie->lsda_encoding & 0xf0) == DW_EH_PE_absptr)
- cie->make_lsda_relative = 1;
+ cie->can_make_lsda_relative = 1;
/* If FDE encoding was not specified, it defaults to
DW_EH_absptr. */
@@ -817,7 +817,6 @@ #define GET_RELOC(buf) \
ENSURE_NO_RELOCS (buf);
this_inf->make_relative = cie->make_relative;
- this_inf->make_lsda_relative = cie->make_lsda_relative;
this_inf->per_encoding_relative
= (cie->per_encoding & 0x70) == DW_EH_PE_pcrel;
}
@@ -862,6 +861,9 @@ #define GET_RELOC(buf) \
be adjusted if any future augmentations do the same thing. */
if (cie->lsda_encoding != DW_EH_PE_omit)
{
+ SKIP_RELOCS (buf);
+ if (cie->can_make_lsda_relative && GET_RELOC (buf))
+ cie->cie_inf->u.cie.make_lsda_relative = 1;
this_inf->lsda_offset = buf - start;
/* If there's no 'z' augmentation, we don't know where the
CFA insns begin. Assume no padding. */
@@ -1097,6 +1099,8 @@ _bfd_elf_gc_mark_fdes (struct bfd_link_i
/* Make the local CIE represent the merged group. */
merged->u.cie.merged = cie;
cie->removed = 0;
+ cie->u.cie.make_lsda_relative
+ = merged->u.cie.make_lsda_relative;
}
}
}
@@ -1248,15 +1252,10 @@ _bfd_elf_eh_frame_section_offset (bfd *o
/* 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].u.fde.cie_inf->make_lsda_relative
- && (offset == (sec_info->entry[mid].offset + 8
- + sec_info->entry[mid].lsda_offset))
- && (sec_info->entry[mid].u.fde.cie_inf->need_lsda_relative
- || !hdr_info->offsets_adjusted))
- {
- sec_info->entry[mid].u.fde.cie_inf->need_lsda_relative = 1;
- return (bfd_vma) -2;
- }
+ && sec_info->entry[mid].u.fde.cie_inf->u.cie.make_lsda_relative
+ && offset == (sec_info->entry[mid].offset + 8
+ + sec_info->entry[mid].lsda_offset))
+ return (bfd_vma) -2;
/* If converting to DW_EH_PE_pcrel, there will be no need for run-time
relocation against DW_CFA_set_loc's arguments. */
@@ -1394,7 +1393,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab
{
/* CIE */
if (ent->make_relative
- || ent->need_lsda_relative
+ || ent->u.cie.make_lsda_relative
|| ent->per_encoding_relative)
{
char *aug;
@@ -1404,7 +1403,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab
/* Need to find 'R' or 'L' augmentation's argument and modify
DW_EH_PE_* value. */
action = ((ent->make_relative ? 1 : 0)
- | (ent->need_lsda_relative ? 2 : 0)
+ | (ent->u.cie.make_lsda_relative ? 2 : 0)
| (ent->per_encoding_relative ? 4 : 0));
extra_string = extra_augmentation_string_bytes (ent);
extra_data = extra_augmentation_data_bytes (ent);
@@ -1548,7 +1547,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab
}
if ((ent->lsda_encoding & 0xf0) == DW_EH_PE_pcrel
- || cie->need_lsda_relative)
+ || cie->u.cie.make_lsda_relative)
{
buf += ent->lsda_offset;
width = get_DW_EH_PE_width (ent->lsda_encoding, ptr_size);
@@ -1558,7 +1557,7 @@ _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 (cie->need_lsda_relative)
+ else if (cie->u.cie.make_lsda_relative)
value -= (sec->output_section->vma + ent->new_offset + 8
+ ent->lsda_offset);
write_value (abfd, buf, value, width);