bfd/
* 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.
This commit is contained in:
parent
6b2cc1401c
commit
fc802241f3
3 changed files with 55 additions and 61 deletions
|
@ -1,3 +1,17 @@
|
|||
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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue