Sign extension bug in .eh_frame_hdr processing
Andreas Schwab
schwab@suse.de
Thu Feb 6 15:49:00 GMT 2003
When bfd_vma is bigger than the target pointer size then the .eh_frame_hdr
processing does not correctly compute the sorted array due to missing sign
extension. This happens on a 32 bit target when a 64 bit BFD is used.
Andreas.
2003-02-06 Andreas Schwab <schwab@suse.de>
* elf-eh-frame.c (get_DW_EH_PE_signed): Define.
(read_value): Add parameter is_signed, use signed extraction if
the value is signed.
(_bfd_elf_write_section_eh_frame): Pass signed flag of the
encoding to read_value.
--- bfd/elf-eh-frame.c.~1.21.~ 2003-02-04 14:21:18.000000000 +0100
+++ bfd/elf-eh-frame.c 2003-02-06 16:03:07.000000000 +0100
@@ -33,7 +33,7 @@ static bfd_signed_vma read_signed_leb128
static int get_DW_EH_PE_width
PARAMS ((int, int));
static bfd_vma read_value
- PARAMS ((bfd *, bfd_byte *, int));
+ PARAMS ((bfd *, bfd_byte *, int, int));
static void write_value
PARAMS ((bfd *, bfd_byte *, bfd_vma, int));
static int cie_compare
@@ -141,22 +141,42 @@ int get_DW_EH_PE_width (encoding, ptr_si
return 0;
}
+#define get_DW_EH_PE_signed(encoding) (((encoding) & DW_EH_PE_signed) != 0)
+
/* Read a width sized value from memory. */
static bfd_vma
-read_value (abfd, buf, width)
+read_value (abfd, buf, width, is_signed)
bfd *abfd;
bfd_byte *buf;
int width;
+ int is_signed;
{
bfd_vma value;
switch (width)
{
- case 2: value = bfd_get_16 (abfd, buf); break;
- case 4: value = bfd_get_32 (abfd, buf); break;
- case 8: value = bfd_get_64 (abfd, buf); break;
- default: BFD_FAIL (); return 0;
+ case 2:
+ if (is_signed)
+ value = bfd_get_signed_16 (abfd, buf);
+ else
+ value = bfd_get_16 (abfd, buf);
+ break;
+ case 4:
+ if (is_signed)
+ value = bfd_get_signed_32 (abfd, buf);
+ else
+ value = bfd_get_32 (abfd, buf);
+ break;
+ case 8:
+ if (is_signed)
+ value = bfd_get_signed_64 (abfd, buf);
+ else
+ value = bfd_get_64 (abfd, buf);
+ break;
+ default:
+ BFD_FAIL ();
+ return 0;
}
return value;
@@ -925,7 +945,9 @@ _bfd_elf_write_section_eh_frame (abfd, i
{
bfd_vma value;
- value = read_value (abfd, buf, per_width);
+ value = read_value (abfd, buf, per_width,
+ get_DW_EH_PE_signed
+ (per_encoding));
value += (sec_info->entry[i].offset
- sec_info->entry[i].new_offset);
write_value (abfd, buf, value, per_width);
@@ -961,7 +983,9 @@ _bfd_elf_write_section_eh_frame (abfd, i
buf += 4;
width = get_DW_EH_PE_width (sec_info->entry[i].fde_encoding,
ptr_size);
- address = value = read_value (abfd, buf, width);
+ address = value = read_value (abfd, buf, width,
+ get_DW_EH_PE_signed
+ (sec_info->entry[i].fde_encoding));
if (value)
{
switch (sec_info->entry[i].fde_encoding & 0xf0)
@@ -1005,7 +1029,9 @@ _bfd_elf_write_section_eh_frame (abfd, i
buf += sec_info->entry[i].lsda_offset;
width = get_DW_EH_PE_width (sec_info->entry[i].lsda_encoding,
ptr_size);
- value = read_value (abfd, buf, width);
+ value = read_value (abfd, buf, width,
+ get_DW_EH_PE_signed
+ (sec_info->entry[i].lsda_encoding));
if (value)
{
if ((sec_info->entry[i].lsda_encoding & 0xf0)
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
More information about the Binutils
mailing list