diff options
author | Alan Modra <amodra@gmail.com> | 2013-12-04 06:44:06 -0600 |
---|---|---|
committer | Adhemerval Zanella <azanella@linux.vnet.ibm.com> | 2013-12-04 07:41:37 -0600 |
commit | 7ec07d9a7b501f1b7d740fda02ba5f39d6d684e5 (patch) | |
tree | 8af2d6588a7c4d7eea36a213f44f3b5823b63f78 /sysdeps/powerpc/powerpc64/dl-machine.h | |
parent | 5162e7dd96efcd9b45c1dc1471a964d45278b1e1 (diff) | |
download | glibc-7ec07d9a7b501f1b7d740fda02ba5f39d6d684e5.tar.gz |
PowerPC64: Report overflow on @h and @ha relocations
This patch updates glibc in accordance with the binutils patch checked in here:
https://sourceware.org/ml/binutils/2013-10/msg00372.html
This changes the various R_PPC64_..._HI and _HA relocations to report
32-bit overflows. The motivation is that existing uses of @h / @ha
are to build up 32-bit offsets (for the "medium model" TOC access
that GCC now defaults to), and we'd really like to see failures at
link / load time rather than silent truncations.
For those rare cases where a modifier is needed to build up a 64-bit
constant, new relocations _HIGH / _HIGHA are supported.
The patch also fixes a bug in overflow checking for the R_PPC64_ADDR30
and R_PPC64_ADDR32 relocations.
Diffstat (limited to 'sysdeps/powerpc/powerpc64/dl-machine.h')
-rw-r--r-- | sysdeps/powerpc/powerpc64/dl-machine.h | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h index 18cf15738a..19fa4fab4b 100644 --- a/sysdeps/powerpc/powerpc64/dl-machine.h +++ b/sysdeps/powerpc/powerpc64/dl-machine.h @@ -669,11 +669,25 @@ elf_machine_rela (struct link_map *map, case R_PPC64_TPREL16_HI: value = elf_machine_tprel (map, sym_map, sym, reloc); + if (dont_expect (value + 0x80000000 >= 0x100000000LL)) + _dl_reloc_overflow (map, "R_PPC64_TPREL16_HI", reloc_addr, refsym); + *(Elf64_Half *) reloc_addr = PPC_HI (value); + break; + + case R_PPC64_TPREL16_HIGH: + value = elf_machine_tprel (map, sym_map, sym, reloc); *(Elf64_Half *) reloc_addr = PPC_HI (value); break; case R_PPC64_TPREL16_HA: value = elf_machine_tprel (map, sym_map, sym, reloc); + if (dont_expect (value + 0x80008000 >= 0x100000000LL)) + _dl_reloc_overflow (map, "R_PPC64_TPREL16_HA", reloc_addr, refsym); + *(Elf64_Half *) reloc_addr = PPC_HA (value); + break; + + case R_PPC64_TPREL16_HIGHA: + value = elf_machine_tprel (map, sym_map, sym, reloc); *(Elf64_Half *) reloc_addr = PPC_HA (value); break; @@ -709,17 +723,23 @@ elf_machine_rela (struct link_map *map, break; case R_PPC64_ADDR16_HI: + if (dont_expect (value + 0x80000000 >= 0x100000000LL)) + _dl_reloc_overflow (map, "R_PPC64_ADDR16_HI", reloc_addr, refsym); + case R_PPC64_ADDR16_HIGH: *(Elf64_Half *) reloc_addr = PPC_HI (value); break; case R_PPC64_ADDR16_HA: + if (dont_expect (value + 0x80008000 >= 0x100000000LL)) + _dl_reloc_overflow (map, "R_PPC64_ADDR16_HA", reloc_addr, refsym); + case R_PPC64_ADDR16_HIGHA: *(Elf64_Half *) reloc_addr = PPC_HA (value); break; case R_PPC64_ADDR30: { Elf64_Addr delta = value - (Elf64_Xword) reloc_addr; - if (dont_expect ((delta + 0x80000000) >= 0x10000000 + if (dont_expect ((delta + 0x80000000) >= 0x100000000LL || (delta & 3) != 0)) _dl_reloc_overflow (map, "R_PPC64_ADDR30", reloc_addr, refsym); BIT_INSERT (*(Elf64_Word *) reloc_addr, delta, 0xfffffffc); @@ -755,7 +775,7 @@ elf_machine_rela (struct link_map *map, return; case R_PPC64_ADDR32: - if (dont_expect ((value + 0x80000000) >= 0x10000000)) + if (dont_expect ((value + 0x80000000) >= 0x100000000LL)) _dl_reloc_overflow (map, "R_PPC64_ADDR32", reloc_addr, refsym); *(Elf64_Word *) reloc_addr = value; return; |