aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog14
-rw-r--r--bfd/elf-bfd.h20
-rw-r--r--bfd/elf-eh-frame.c82
3 files changed, 55 insertions, 61 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 46e90c1..91b48bc 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,19 @@
2007-12-15 Richard Sandiford <rsandifo@nildram.co.uk>
+ * elf-bfd.h (eh_cie_fde): Replace u.cie.merged with a union of
+ a merged field and a sec field.
+ (eh_frame_hdr_info): Remove offsets_adjusted.
+ * elf-eh-frame.c (_bfd_elf_parse_eh_frame): Update accesses to
+ the CIE merged field.
+ (_bfd_elf_gc_mark_fdes): Likewise.
+ (_bfd_elf_discard_section_eh_frame): Likewise. Set u.cie.u.sec
+ when clearing the removed flag.
+ (_bfd_elf_eh_frame_section_offset): Remove offsets_adjusted handling.
+ (_bfd_elf_write_section_eh_frame): Likewise. Apply output_offsets
+ where appropriate.
+
+2007-12-15 Richard Sandiford <rsandifo@nildram.co.uk>
+
* 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.
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 4b6c1af..918eec3 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -277,11 +277,20 @@ struct eh_cie_fde
} fde;
struct {
/* In general, equivalent CIEs are grouped together, with one CIE
- representing all the others in a group. If REMOVED == 0,
- this CIE is the group representative. If REMOVED == 1,
- following this pointer brings us "closer" to the CIE's group
- representative, and reapplying always gives the representative. */
- struct eh_cie_fde *merged;
+ representing all the others in a group.
+
+ If REMOVED == 0, this CIE is the group representative, and
+ U.SEC points to the .eh_frame section that contains the CIE.
+
+ If REMOVED == 1, this CIE is the group representative if
+ U.MERGED is a self pointer. Otherwise, following U.MERGED
+ brings us "closer" to the CIE's group representative;
+ if U.MERGED is not the group representative, then
+ U.MERGED->U.MERGED is. */
+ union {
+ struct eh_cie_fde *merged;
+ asection *sec;
+ } u;
/* True if we have marked relocations associated with this CIE. */
unsigned int gc_mark : 1;
@@ -355,7 +364,6 @@ struct eh_frame_hdr_info
We build it if we successfully read all .eh_frame input sections
and recognize them. */
bfd_boolean table;
- bfd_boolean offsets_adjusted;
};
/* ELF linker hash table. */
diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
index 5827a24..f8386d3 100644
--- a/bfd/elf-eh-frame.c
+++ b/bfd/elf-eh-frame.c
@@ -935,7 +935,7 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
}
cie = (struct cie *) *loc;
}
- this_inf->u.cie.merged = cie->cie_inf;
+ this_inf->u.cie.u.merged = cie->cie_inf;
ecies[ecie_count].cie = cie;
ecies[ecie_count++].local_cie = this_inf;
}
@@ -1019,7 +1019,7 @@ _bfd_elf_gc_mark_fdes (struct bfd_link_info *info, asection *sec,
/* At this stage, all cie_inf fields point to local CIEs, so we
can use the same cookie to refer to them. */
cie = fde->u.fde.cie_inf;
- merged = cie->u.cie.merged;
+ merged = cie->u.cie.u.merged;
if (!merged->u.cie.gc_mark)
{
merged->u.cie.gc_mark = 1;
@@ -1079,19 +1079,20 @@ _bfd_elf_discard_section_eh_frame
cie = ent->u.fde.cie_inf;
if (cie->removed)
{
- merged = cie->u.cie.merged;
+ merged = cie->u.cie.u.merged;
if (!merged->removed)
/* We have decided to keep the group representative. */
ent->u.fde.cie_inf = merged;
- else if (merged->u.cie.merged != merged)
+ else if (merged->u.cie.u.merged != merged)
/* We didn't keep the original group representative,
but we did keep an alternative. */
- ent->u.fde.cie_inf = merged->u.cie.merged;
+ ent->u.fde.cie_inf = merged->u.cie.u.merged;
else
{
/* Make the local CIE represent the merged group. */
- merged->u.cie.merged = cie;
+ merged->u.cie.u.merged = cie;
cie->removed = 0;
+ cie->u.cie.u.sec = sec;
cie->u.cie.make_lsda_relative
= merged->u.cie.make_lsda_relative;
}
@@ -1211,8 +1212,6 @@ _bfd_elf_eh_frame_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED,
htab = elf_hash_table (info);
hdr_info = &htab->eh_info;
- if (hdr_info->offsets_adjusted)
- offset += sec->output_offset;
lo = 0;
hi = sec_info->count;
@@ -1265,8 +1264,6 @@ _bfd_elf_eh_frame_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED,
return (bfd_vma) -2;
}
- if (hdr_info->offsets_adjusted)
- offset -= sec->output_offset;
/* Any new augmentation bytes go before the first relocation. */
return (offset + sec_info->entry[mid].new_offset
- sec_info->entry[mid].offset
@@ -1301,38 +1298,6 @@ _bfd_elf_write_section_eh_frame (bfd *abfd,
htab = elf_hash_table (info);
hdr_info = &htab->eh_info;
- /* First convert all offsets to output section offsets, so that a
- CIE offset is valid if the CIE is used by a FDE from some other
- section. This can happen when duplicate CIEs are deleted in
- _bfd_elf_discard_section_eh_frame. We do all sections here because
- this function might not be called on sections in the same order as
- _bfd_elf_discard_section_eh_frame. */
- if (!hdr_info->offsets_adjusted)
- {
- bfd *ibfd;
- asection *eh;
- struct eh_frame_sec_info *eh_inf;
-
- for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
- {
- if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
- || (ibfd->flags & DYNAMIC) != 0)
- continue;
-
- eh = bfd_get_section_by_name (ibfd, ".eh_frame");
- if (eh == NULL || eh->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
- continue;
-
- eh_inf = elf_section_data (eh)->sec_info;
- for (ent = eh_inf->entry; ent < eh_inf->entry + eh_inf->count; ++ent)
- {
- ent->offset += eh->output_offset;
- ent->new_offset += eh->output_offset;
- }
- }
- hdr_info->offsets_adjusted = TRUE;
- }
-
if (hdr_info->table && hdr_info->array == NULL)
hdr_info->array
= bfd_malloc (hdr_info->fde_count * sizeof(*hdr_info->array));
@@ -1346,13 +1311,11 @@ _bfd_elf_write_section_eh_frame (bfd *abfd,
not reordered */
for (ent = sec_info->entry + sec_info->count; ent-- != sec_info->entry;)
if (!ent->removed && ent->new_offset > ent->offset)
- memmove (contents + ent->new_offset - sec->output_offset,
- contents + ent->offset - sec->output_offset, ent->size);
+ memmove (contents + ent->new_offset, contents + ent->offset, ent->size);
for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
if (!ent->removed && ent->new_offset < ent->offset)
- memmove (contents + ent->new_offset - sec->output_offset,
- contents + ent->offset - sec->output_offset, ent->size);
+ memmove (contents + ent->new_offset, contents + ent->offset, ent->size);
for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
{
@@ -1369,7 +1332,7 @@ _bfd_elf_write_section_eh_frame (bfd *abfd,
continue;
}
- buf = contents + ent->new_offset - sec->output_offset;
+ buf = contents + ent->new_offset;
end = buf + ent->size;
new_size = size_of_output_cie_fde (ent, ptr_size);
@@ -1495,7 +1458,8 @@ _bfd_elf_write_section_eh_frame (bfd *abfd,
/* Skip length. */
cie = ent->u.fde.cie_inf;
buf += 4;
- value = ent->new_offset + 4 - cie->new_offset;
+ value = ((ent->new_offset + sec->output_offset + 4)
+ - (cie->new_offset + cie->u.cie.u.sec->output_offset));
bfd_put_32 (abfd, value, buf);
buf += 4;
width = get_DW_EH_PE_width (ent->fde_encoding, ptr_size);
@@ -1520,11 +1484,15 @@ _bfd_elf_write_section_eh_frame (bfd *abfd,
break;
case DW_EH_PE_pcrel:
value += ent->offset - ent->new_offset;
- address += sec->output_section->vma + ent->offset + 8;
+ address += (sec->output_section->vma
+ + sec->output_offset
+ + ent->offset + 8);
break;
}
if (ent->make_relative)
- value -= sec->output_section->vma + ent->new_offset + 8;
+ value -= (sec->output_section->vma
+ + sec->output_offset
+ + ent->new_offset + 8);
write_value (abfd, buf, value, width);
}
@@ -1534,7 +1502,9 @@ _bfd_elf_write_section_eh_frame (bfd *abfd,
{
hdr_info->array[hdr_info->array_count].initial_loc = address;
hdr_info->array[hdr_info->array_count++].fde
- = sec->output_section->vma + ent->new_offset;
+ = (sec->output_section->vma
+ + sec->output_offset
+ + ent->new_offset);
}
if ((ent->lsda_encoding & 0xf0) == DW_EH_PE_pcrel
@@ -1549,8 +1519,9 @@ _bfd_elf_write_section_eh_frame (bfd *abfd,
if ((ent->lsda_encoding & 0xf0) == DW_EH_PE_pcrel)
value += ent->offset - ent->new_offset;
else if (cie->u.cie.make_lsda_relative)
- value -= (sec->output_section->vma + ent->new_offset + 8
- + ent->lsda_offset);
+ value -= (sec->output_section->vma
+ + sec->output_offset
+ + ent->new_offset + 8 + ent->lsda_offset);
write_value (abfd, buf, value, width);
}
}
@@ -1587,8 +1558,9 @@ _bfd_elf_write_section_eh_frame (bfd *abfd,
if ((ent->fde_encoding & 0xf0) == DW_EH_PE_pcrel)
value += ent->offset + 8 - new_offset;
if (ent->make_relative)
- value -= sec->output_section->vma + new_offset
- + ent->set_loc[cnt];
+ value -= (sec->output_section->vma
+ + sec->output_offset
+ + new_offset + ent->set_loc[cnt]);
write_value (abfd, buf, value, width);
}
}