summaryrefslogtreecommitdiff
path: root/bfd/elfxx-mips.h
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2022-12-09 17:58:58 +1030
committerAlan Modra <amodra@gmail.com>2022-12-09 21:38:46 +1030
commit73425813c1b6286fd589fcf0ef9335e8240137a9 (patch)
tree41b84b5b2ddeb40c9fddd0e528827114a757bdb9 /bfd/elfxx-mips.h
parent8b272d7671fb9af34fe14bd274e97f05bb299635 (diff)
downloadbinutils-gdb-73425813c1b6286fd589fcf0ef9335e8240137a9.tar.gz
PR28306, segfault in _bfd_mips_elf_reloc_unshuffle
Access to section data during relocation processing should be bounds checked, as it is in bfd_perform_relocation. bfd_perform_relocation does these checks after any special_function is called. So a reloc special_function needs to do its own bounds checking before accessing section data. This patch adds many such checks to the mips backend. Checking mips relocs is not without some difficulty. See the comment in _bfd_mips_reloc_offset_in_range. In a multitple reloc sequence applied to the same location, relocs that may appear somewhere other than the last one of the sequence need to be treated specially since they apply to the addend for the next relocation rather than the section contents. If the addend is in the section then it needs to be checked but not when the addend is in the reloc. check_inplace handles this situation. _bfd_mips_reloc_offset_in_range with check_shuffle handles the case where contents are shuffled before applying the relocation. PR 28306 * elf32-mips.c (_bfd_mips_elf32_gprel16_reloc): Check reloc address using _bfd_mips_reloc_offset_in_range. (gprel32_with_gp, mips16_gprel_reloc): Likewise. * elf64-mips.c (mips_elf64_gprel32_reloc): Likewise. (mips16_gprel_reloc): Likewise. * elfn32-mips.c (mips16_gprel_reloc): Likewise. (gprel32_with_gp): Check reloc address using bfd_reloc_offset_in_range. * elfxx-mips.h (enum reloc_check): Define. (_bfd_mips_reloc_offset_in_range): Declare. * elfxx-mips.c (needs_shuffle): New function. (_bfd_mips_elf_reloc_unshuffle, _bfd_mips_elf_reloc_shuffle): Use it. (_bfd_mips_reloc_offset_in_range): New function. (_bfd_mips_elf_gprel16_with_gp): Move reloc address checks to partial_inplace handling. Use bfd_reloc_offset_in_range. (_bfd_mips_elf_lo16_reloc): Check reloc address using bfd_reloc_offset_in_range. (_bfd_mips_elf_generic_reloc): Check reloc address using _bfd_mips_reloc_offset_in_range. (mips_elf_calculate_relocation): Check reloc address before calling mips_elf_nullify_got_load. (_bfd_mips_elf_check_relocs): Likewise. (mips_elf_read_rel_addend): Add sec param, check reloc address before reading. Adjust callers. (mips_elf_add_lo16_rel_addend): Add sec param, adjust callers.
Diffstat (limited to 'bfd/elfxx-mips.h')
-rw-r--r--bfd/elfxx-mips.h9
1 files changed, 9 insertions, 0 deletions
diff --git a/bfd/elfxx-mips.h b/bfd/elfxx-mips.h
index af6d14c6ce3..6b22fdab3ae 100644
--- a/bfd/elfxx-mips.h
+++ b/bfd/elfxx-mips.h
@@ -22,6 +22,13 @@
#include "elf/internal.h"
#include "elf/mips.h"
+enum reloc_check
+{
+ check_std,
+ check_inplace,
+ check_shuffle
+};
+
extern bool _bfd_mips_elf_mkobject
(bfd *);
extern bool _bfd_mips_elf_new_section_hook
@@ -129,6 +136,8 @@ extern void _bfd_mips_elf_reloc_unshuffle
(bfd *, int, bool, bfd_byte *);
extern void _bfd_mips_elf_reloc_shuffle
(bfd *, int, bool, bfd_byte *);
+extern bool _bfd_mips_reloc_offset_in_range
+ (bfd *, asection *, arelent *, enum reloc_check);
extern bfd_reloc_status_type _bfd_mips_elf_gprel16_with_gp
(bfd *, asymbol *, arelent *, asection *, bool, void *, bfd_vma);
extern bfd_reloc_status_type _bfd_mips_elf32_gprel16_reloc