From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 17692 invoked by alias); 2 Dec 2007 20:37:51 -0000 Received: (qmail 17677 invoked by uid 22791); 2 Dec 2007 20:37:50 -0000 X-Spam-Check-By: sourceware.org Received: from smtp.nildram.co.uk (HELO smtp.nildram.co.uk) (195.112.4.54) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sun, 02 Dec 2007 20:37:40 +0000 Received: from firetop.home (85-211-136-23.dyn.gotadsl.co.uk [85.211.136.23]) by smtp.nildram.co.uk (Postfix) with ESMTP id 6DB8B2B68FF for ; Sun, 2 Dec 2007 20:37:29 +0000 (GMT) Received: from richard by firetop.home with local (Exim 4.63) (envelope-from ) id 1IyvZE-0007iP-Mx for binutils@sourceware.org; Sun, 02 Dec 2007 20:37:32 +0000 From: Richard Sandiford To: binutils@sourceware.org Mail-Followup-To: binutils@sourceware.org, rsandifo@nildram.co.uk Subject: [PATCH 6/7] Fix --gc-sections for C++ MIPS ELF References: <87r6i4svjg.fsf@firetop.home> Date: Sun, 02 Dec 2007 20:37:00 -0000 In-Reply-To: <87r6i4svjg.fsf@firetop.home> (Richard Sandiford's message of "Sun\, 02 Dec 2007 20\:15\:15 +0000") Message-ID: <871wa4suib.fsf@firetop.home> User-Agent: Gnus/5.110006 (No Gnus v0.6) Emacs/21.4 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org X-SW-Source: 2007-12/txt/msg00006.txt.bz2 This patch moves the other CIE-specific flags to u.cie. The following flags only apply to CIEs: per_encoding_relative add_fde_encoding add_augmentation_size make_relative The first two don't affect the FDE code at all, so they might as well remain CIE-only. The last two do affect the FDE code, so we could either: (1) make the FDE flags a copy of the CIE flags or (2) keep the flags CIE-specific and move them to u.cie There's not much in it, but (1) helps to simplify a couple of things, so I went for that. I'm happy to do (2) if you prefer. Richard bfd/ * elf-bfd.h (eh_cie_fde): Move add_fde_encoding and per_encoding_relative to u.cie. Add commentary. * elf-eh-frame.c (cie): Remove make_relative. (extra_augmentation_string_bytes): Update use of add_fde_encoding. (extra_augmentation_data_bytes): Likewise. Use an FDE's own add_augmentation_size field, rather than referring to the CIE. (_bfd_elf_parse_eh_frame): Don't set the struct cie make_relative field; set the eh_cie_fde field directly. Update setting of add_fde_encoding and per_encoding_relative. Copy make_relative and add_augmentation_size from the CIE to the FDE. (_bfd_elf_discard_section_eh_frame): Use the FDE's own make_relative field. (_bfd_elf_eh_frame_section_offset): Likewise. (_bfd_elf_write_section_eh_frame): Update accesses to add_fde_encoding and per_encoding_relative. Use the FDE's own make_relative and add_augmentation_size fields. Index: bfd/elf-bfd.h =================================================================== --- bfd/elf-bfd.h 2007-12-02 17:40:41.000000000 +0000 +++ bfd/elf-bfd.h 2007-12-02 17:46:04.000000000 +0000 @@ -290,6 +290,14 @@ struct eh_cie_fde a PC-relative one. It is the group representative's setting that matters. */ unsigned int make_lsda_relative : 1; + + /* True if the CIE contains personality data and if that data + uses a PC-relative encoding. */ + unsigned int per_encoding_relative : 1; + + /* True if we need to add an 'R' (FDE encoding) entry to the + CIE's augmentation data. */ + unsigned int add_fde_encoding : 1; } cie; } u; unsigned int reloc_index; @@ -299,12 +307,22 @@ struct eh_cie_fde unsigned int fde_encoding : 8; unsigned int lsda_encoding : 8; unsigned int lsda_offset : 8; + + /* True if this entry represents a CIE, false if it represents an FDE. */ unsigned int cie : 1; + + /* True if this entry is currently marked for removal. */ unsigned int removed : 1; + + /* True if we need to add a 'z' (augmentation size) entry to the CIE's + augmentation data, and an associated byte to each of the CIE's FDEs. */ unsigned int add_augmentation_size : 1; - unsigned int add_fde_encoding : 1; + + /* True if we have decided to convert absolute FDE relocations into + relative ones. This applies to the first relocation in the FDE, + which is against the code that the FDE describes. */ unsigned int make_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:41:29.000000000 +0000 +++ bfd/elf-eh-frame.c 2007-12-02 17:45:12.000000000 +0000 @@ -49,7 +49,6 @@ struct cie unsigned char lsda_encoding; unsigned char fde_encoding; unsigned char initial_insn_length; - unsigned char make_relative; unsigned char can_make_lsda_relative; unsigned char initial_instructions[50]; }; @@ -283,7 +282,7 @@ extra_augmentation_string_bytes (struct { if (entry->add_augmentation_size) size++; - if (entry->add_fde_encoding) + if (entry->u.cie.add_fde_encoding) size++; } return size; @@ -295,18 +294,10 @@ extra_augmentation_string_bytes (struct extra_augmentation_data_bytes (struct eh_cie_fde *entry) { unsigned int size = 0; - if (entry->cie) - { - if (entry->add_augmentation_size) - size++; - if (entry->add_fde_encoding) - size++; - } - else - { - if (entry->u.fde.cie_inf->add_augmentation_size) - size++; - } + if (entry->add_augmentation_size) + size++; + if (entry->cie && entry->u.cie.add_fde_encoding) + size++; return size; } @@ -780,7 +771,7 @@ #define GET_RELOC(buf) \ (abfd, info, sec))) { if ((cie->fde_encoding & 0xf0) == DW_EH_PE_absptr) - cie->make_relative = 1; + this_inf->make_relative = 1; /* If the CIE doesn't already have an 'R' entry, it's fairly easy to add one, provided that there's no aligned data after the augmentation string. */ @@ -789,8 +780,8 @@ #define GET_RELOC(buf) \ { if (*cie->augmentation == 0) this_inf->add_augmentation_size = 1; - this_inf->add_fde_encoding = 1; - cie->make_relative = 1; + this_inf->u.cie.add_fde_encoding = 1; + this_inf->make_relative = 1; } } @@ -816,8 +807,7 @@ #define GET_RELOC(buf) \ buf += initial_insn_length; ENSURE_NO_RELOCS (buf); - this_inf->make_relative = cie->make_relative; - this_inf->per_encoding_relative + this_inf->u.cie.per_encoding_relative = (cie->per_encoding & 0x70) == DW_EH_PE_pcrel; } else @@ -835,6 +825,9 @@ #define GET_RELOC(buf) \ REQUIRE (ecie != ecies + ecie_count); cie = ecie->cie; this_inf->u.fde.cie_inf = ecie->local_cie; + this_inf->make_relative = ecie->local_cie->make_relative; + this_inf->add_augmentation_size + = ecie->local_cie->add_augmentation_size; ENSURE_NO_RELOCS (buf); REQUIRE (GET_RELOC (buf)); @@ -900,7 +893,7 @@ #define GET_RELOC(buf) \ } if (set_loc_count && ((cie->fde_encoding & 0xf0) == DW_EH_PE_pcrel - || cie->make_relative)) + || this_inf->make_relative)) { unsigned int cnt; bfd_byte *p; @@ -1068,7 +1061,7 @@ _bfd_elf_gc_mark_fdes (struct bfd_link_i { if (info->shared && (((ent->fde_encoding & 0xf0) == DW_EH_PE_absptr - && ent->u.fde.cie_inf->make_relative == 0) + && ent->make_relative == 0) || (ent->fde_encoding & 0xf0) == DW_EH_PE_aligned)) { /* If a shared library uses absolute pointers @@ -1245,7 +1238,7 @@ _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].u.fde.cie_inf->make_relative + && sec_info->entry[mid].make_relative && offset == sec_info->entry[mid].offset + 8) return (bfd_vma) -2; @@ -1260,9 +1253,7 @@ _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 DW_CFA_set_loc's arguments. */ if (sec_info->entry[mid].set_loc - && (sec_info->entry[mid].cie - ? sec_info->entry[mid].make_relative - : sec_info->entry[mid].u.fde.cie_inf->make_relative) + && sec_info->entry[mid].make_relative && (offset >= sec_info->entry[mid].offset + 8 + sec_info->entry[mid].set_loc[1])) { @@ -1394,7 +1385,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab /* CIE */ if (ent->make_relative || ent->u.cie.make_lsda_relative - || ent->per_encoding_relative) + || ent->u.cie.per_encoding_relative) { char *aug; unsigned int action, extra_string, extra_data; @@ -1404,7 +1395,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab DW_EH_PE_* value. */ action = ((ent->make_relative ? 1 : 0) | (ent->u.cie.make_lsda_relative ? 2 : 0) - | (ent->per_encoding_relative ? 4 : 0)); + | (ent->u.cie.per_encoding_relative ? 4 : 0)); extra_string = extra_augmentation_string_bytes (ent); extra_data = extra_augmentation_data_bytes (ent); @@ -1434,7 +1425,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab *aug++ = 'z'; *buf++ = extra_data - 1; } - if (ent->add_fde_encoding) + if (ent->u.cie.add_fde_encoding) { BFD_ASSERT (action & 1); *aug++ = 'R'; @@ -1459,7 +1450,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab per_width = get_DW_EH_PE_width (per_encoding, ptr_size); BFD_ASSERT (per_width != 0); BFD_ASSERT (((per_encoding & 0x70) == DW_EH_PE_pcrel) - == ent->per_encoding_relative); + == ent->u.cie.per_encoding_relative); if ((per_encoding & 0xf0) == DW_EH_PE_aligned) buf = (contents + ((buf - contents + per_width - 1) @@ -1532,7 +1523,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab address += sec->output_section->vma + ent->offset + 8; break; } - if (cie->make_relative) + if (ent->make_relative) value -= sec->output_section->vma + ent->new_offset + 8; write_value (abfd, buf, value, width); } @@ -1563,7 +1554,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab write_value (abfd, buf, value, width); } } - else if (cie->add_augmentation_size) + else if (ent->add_augmentation_size) { /* Skip the PC and length and insert a zero byte for the augmentation size. */ @@ -1595,7 +1586,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 (cie->make_relative) + if (ent->make_relative) value -= sec->output_section->vma + new_offset + ent->set_loc[cnt]; write_value (abfd, buf, value, width);