mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-25 13:27:26 +08:00
Test for overflow in eh_frame_hdr entries and for overlapping FDEs
With larger binaries on 64-bit systems, or indeed just binaries that have a large gap between text and data, it is possible for the .eh_frame_hdr lookup table entry values to overflow a signed 32-bit relative offset. It is also a requirement for the glibc FDE lookup code that only one FDE claim to cover any given address. * elf-bfd.h (struct eh_frame_array_ent): Add "range". * elf-eh-frame.c (_bfd_elf_write_section_eh_frame): Stash address range of FDEs to hdr_info->array. (_bfd_elf_write_section_eh_frame_hdr): Report overflow in .eh_frame_hdr entries, and overlapping FDEs.
This commit is contained in:
@ -1,3 +1,11 @@
|
|||||||
|
2014-09-12 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* elf-bfd.h (struct eh_frame_array_ent): Add "range".
|
||||||
|
* elf-eh-frame.c (_bfd_elf_write_section_eh_frame): Stash address
|
||||||
|
range of FDEs to hdr_info->array.
|
||||||
|
(_bfd_elf_write_section_eh_frame_hdr): Report overflow in
|
||||||
|
.eh_frame_hdr entries, and overlapping FDEs.
|
||||||
|
|
||||||
2014-09-10 Alan Modra <amodra@gmail.com>
|
2014-09-10 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* elf.c (assign_file_positions_except_relocs): Move section header
|
* elf.c (assign_file_positions_except_relocs): Move section header
|
||||||
|
@ -372,6 +372,7 @@ struct eh_frame_sec_info
|
|||||||
struct eh_frame_array_ent
|
struct eh_frame_array_ent
|
||||||
{
|
{
|
||||||
bfd_vma initial_loc;
|
bfd_vma initial_loc;
|
||||||
|
bfd_size_type range;
|
||||||
bfd_vma fde;
|
bfd_vma fde;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1632,6 +1632,8 @@ _bfd_elf_write_section_eh_frame (bfd *abfd,
|
|||||||
if (sizeof (address) > 4 && ptr_size == 4)
|
if (sizeof (address) > 4 && ptr_size == 4)
|
||||||
address &= 0xffffffff;
|
address &= 0xffffffff;
|
||||||
hdr_info->array[hdr_info->array_count].initial_loc = address;
|
hdr_info->array[hdr_info->array_count].initial_loc = address;
|
||||||
|
hdr_info->array[hdr_info->array_count].range
|
||||||
|
= read_value (abfd, buf + width, width, FALSE);
|
||||||
hdr_info->array[hdr_info->array_count++].fde
|
hdr_info->array[hdr_info->array_count++].fde
|
||||||
= (sec->output_section->vma
|
= (sec->output_section->vma
|
||||||
+ sec->output_offset
|
+ sec->output_offset
|
||||||
@ -1805,26 +1807,55 @@ _bfd_elf_write_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
|
|||||||
if (contents[2] != DW_EH_PE_omit)
|
if (contents[2] != DW_EH_PE_omit)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
bfd_boolean overlap, overflow;
|
||||||
|
|
||||||
bfd_put_32 (abfd, hdr_info->fde_count, contents + EH_FRAME_HDR_SIZE);
|
bfd_put_32 (abfd, hdr_info->fde_count, contents + EH_FRAME_HDR_SIZE);
|
||||||
qsort (hdr_info->array, hdr_info->fde_count,
|
qsort (hdr_info->array, hdr_info->fde_count,
|
||||||
sizeof (*hdr_info->array), vma_compare);
|
sizeof (*hdr_info->array), vma_compare);
|
||||||
|
overlap = FALSE;
|
||||||
|
overflow = FALSE;
|
||||||
for (i = 0; i < hdr_info->fde_count; i++)
|
for (i = 0; i < hdr_info->fde_count; i++)
|
||||||
{
|
{
|
||||||
bfd_put_32 (abfd,
|
bfd_vma val;
|
||||||
hdr_info->array[i].initial_loc
|
|
||||||
- sec->output_section->vma,
|
val = hdr_info->array[i].initial_loc - sec->output_section->vma;
|
||||||
contents + EH_FRAME_HDR_SIZE + i * 8 + 4);
|
val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
|
||||||
bfd_put_32 (abfd,
|
if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64
|
||||||
hdr_info->array[i].fde - sec->output_section->vma,
|
&& (hdr_info->array[i].initial_loc
|
||||||
contents + EH_FRAME_HDR_SIZE + i * 8 + 8);
|
!= sec->output_section->vma + val))
|
||||||
|
overflow = TRUE;
|
||||||
|
bfd_put_32 (abfd, val, contents + EH_FRAME_HDR_SIZE + i * 8 + 4);
|
||||||
|
val = hdr_info->array[i].fde - sec->output_section->vma;
|
||||||
|
val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
|
||||||
|
if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64
|
||||||
|
&& (hdr_info->array[i].fde
|
||||||
|
!= sec->output_section->vma + val))
|
||||||
|
overflow = TRUE;
|
||||||
|
bfd_put_32 (abfd, val, contents + EH_FRAME_HDR_SIZE + i * 8 + 8);
|
||||||
|
if (i != 0
|
||||||
|
&& (hdr_info->array[i].initial_loc
|
||||||
|
< (hdr_info->array[i - 1].initial_loc
|
||||||
|
+ hdr_info->array[i - 1].range)))
|
||||||
|
overlap = TRUE;
|
||||||
|
}
|
||||||
|
if (overflow)
|
||||||
|
(*info->callbacks->einfo)
|
||||||
|
(_("%P: .eh_frame_hdr entry overflow.\n"));
|
||||||
|
if (overlap)
|
||||||
|
(*info->callbacks->einfo)
|
||||||
|
(_("%P: .eh_frame_hdr refers to overlapping FDEs.\n"));
|
||||||
|
if (overflow || overlap)
|
||||||
|
{
|
||||||
|
bfd_set_error (bfd_error_bad_value);
|
||||||
|
retval = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: octets_per_byte. */
|
/* FIXME: octets_per_byte. */
|
||||||
retval = bfd_set_section_contents (abfd, sec->output_section, contents,
|
if (!bfd_set_section_contents (abfd, sec->output_section, contents,
|
||||||
(file_ptr) sec->output_offset,
|
(file_ptr) sec->output_offset,
|
||||||
sec->size);
|
sec->size))
|
||||||
|
retval = FALSE;
|
||||||
free (contents);
|
free (contents);
|
||||||
}
|
}
|
||||||
if (hdr_info->array != NULL)
|
if (hdr_info->array != NULL)
|
||||||
|
Reference in New Issue
Block a user