This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[PATCH] Fix --eh-frame-hdr with DW_EH_PE_pcrel personality encoding
- From: Jakub Jelinek <jakub at redhat dot com>
- To: binutils at sources dot redhat dot com
- Cc: davem at redhat dot com, Richard Smith <richard at ex-parrot dot com>, Daniel Jacobowitz <drow at mvista dot com>
- Date: Mon, 22 Apr 2002 14:19:55 +0200
- Subject: [PATCH] Fix --eh-frame-hdr with DW_EH_PE_pcrel personality encoding
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
I've commited the following patch to fix --eh-frame-hdr handling.
I forgot to adjust personalities when reshuffling FDE/CIEs if personalities
are DW_EH_PE_pcrel encoded. It is quite serious bug, will see if I can
cook up a test for gcc configury for this.
Daniel, ok to commit to 2.12 branch? Is 2.12.1 on the horizon?
2002-04-22 Richard Smith <richard@ex-parrot.com>
Jakub Jelinek <jakub@redhat.com>
* elf-eh-frame.c (struct eh_cie_fde): Add per_encoding_relative.
(_bfd_elf_discard_section_eh_frame): Set it for CIEs with pcrel
encoded personality.
(_bfd_elf_write_section_eh_frame): Adjust pcrel encoded personality
for CIE/FDE removal.
--- bfd/elf-eh-frame.c.jj Tue Feb 19 13:37:48 2002
+++ bfd/elf-eh-frame.c Mon Apr 22 13:57:23 2002
@@ -64,6 +64,7 @@ struct eh_cie_fde
unsigned char removed : 1;
unsigned char make_relative : 1;
unsigned char make_lsda_relative : 1;
+ unsigned char per_encoding_relative : 1;
};
struct eh_frame_sec_info
@@ -469,6 +470,8 @@ _bfd_elf_discard_section_eh_frame (abfd,
= cie.make_relative;
sec_info->entry[last_cie_ndx].make_lsda_relative
= cie.make_lsda_relative;
+ sec_info->entry[last_cie_ndx].per_encoding_relative
+ = (cie.per_encoding & 0x70) == DW_EH_PE_pcrel;
}
}
@@ -689,6 +692,7 @@ _bfd_elf_discard_section_eh_frame (abfd,
{
sec_info->entry[i].make_relative = make_relative;
sec_info->entry[i].make_lsda_relative = make_lsda_relative;
+ sec_info->entry[i].per_encoding_relative = 0;
}
}
else if (sec_info->entry[i].cie && sec_info->entry[i].sec == sec)
@@ -947,7 +951,8 @@ _bfd_elf_write_section_eh_frame (abfd, s
/* CIE */
cie_offset = sec_info->entry[i].new_offset;
if (sec_info->entry[i].make_relative
- || sec_info->entry[i].make_lsda_relative)
+ || sec_info->entry[i].make_lsda_relative
+ || sec_info->entry[i].per_encoding_relative)
{
unsigned char *aug;
unsigned int action;
@@ -956,7 +961,8 @@ _bfd_elf_write_section_eh_frame (abfd, s
/* Need to find 'R' or 'L' augmentation's argument and modify
DW_EH_PE_* value. */
action = (sec_info->entry[i].make_relative ? 1 : 0)
- | (sec_info->entry[i].make_lsda_relative ? 2 : 0);
+ | (sec_info->entry[i].make_lsda_relative ? 2 : 0)
+ | (sec_info->entry[i].per_encoding_relative ? 4 : 0);
buf = contents + sec_info->entry[i].offset;
/* Skip length, id and version. */
buf += 9;
@@ -988,10 +994,22 @@ _bfd_elf_write_section_eh_frame (abfd, s
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)
+ == sec_info->entry[i].per_encoding_relative);
if ((per_encoding & 0xf0) == DW_EH_PE_aligned)
buf = (contents
+ ((buf - contents + per_width - 1)
& ~((bfd_size_type) per_width - 1)));
+ if (action & 4)
+ {
+ bfd_vma value;
+
+ value = read_value (abfd, buf, per_width);
+ value += (sec_info->entry[i].offset
+ - sec_info->entry[i].new_offset);
+ write_value (abfd, buf, value, per_width);
+ action &= ~4;
+ }
buf += per_width;
break;
case 'R':
Jakub