} 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;
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. */
}
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;
}
/* 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;
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;
}
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;
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
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));
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)
{
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);
/* 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);
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);
}
{
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
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);
}
}
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);
}
}