mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git
synced 2026-04-18 03:23:53 -04:00
modpost: work around unaligned data access error
With the latest binutils, modpost fails with a bus error on some
architectures such as ARM and sparc64.
Since binutils commit 1f1b5e506bf0 ("bfd/ELF: restrict file alignment
for object files"), the byte offset to each section (sh_offset) in
relocatable ELF is no longer guaranteed to be aligned.
modpost parses MODULE_DEVICE_TABLE() data structures, which are usually
located in the .rodata section. If it is not properly aligned, unaligned
access errors may occur.
To address the issue, this commit imports the get_unaligned() helper
from include/linux/unaligned.h.
The get_unaligned_native() helper caters to the endianness in addition
to handling the unaligned access.
I slightly refactored do_pcmcia_entry() and do_input() to avoid writing
back to an unaligned address. (We would need the put_unaligned() helper
to do that.)
The addend_*_rel() functions need similar adjustments because the .text
sections are not aligned either.
It seems that the .symtab, .rel.* and .rela.* sections are still aligned.
Keep normal pointer access for these sections to avoid unnecessary
performance costs.
Reported-by: Paulo Pisati <paolo.pisati@canonical.com>
Reported-by: Matthias Klose <doko@debian.org>
Closes: https://sourceware.org/bugzilla/show_bug.cgi?id=32435
Reported-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
Closes: https://sourceware.org/bugzilla/show_bug.cgi?id=32493
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Tested-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
This commit is contained in:
@@ -1138,9 +1138,9 @@ static Elf_Addr addend_386_rel(uint32_t *location, unsigned int r_type)
|
||||
{
|
||||
switch (r_type) {
|
||||
case R_386_32:
|
||||
return TO_NATIVE(*location);
|
||||
return get_unaligned_native(location);
|
||||
case R_386_PC32:
|
||||
return TO_NATIVE(*location) + 4;
|
||||
return get_unaligned_native(location) + 4;
|
||||
}
|
||||
|
||||
return (Elf_Addr)(-1);
|
||||
@@ -1161,24 +1161,24 @@ static Elf_Addr addend_arm_rel(void *loc, Elf_Sym *sym, unsigned int r_type)
|
||||
switch (r_type) {
|
||||
case R_ARM_ABS32:
|
||||
case R_ARM_REL32:
|
||||
inst = TO_NATIVE(*(uint32_t *)loc);
|
||||
inst = get_unaligned_native((uint32_t *)loc);
|
||||
return inst + sym->st_value;
|
||||
case R_ARM_MOVW_ABS_NC:
|
||||
case R_ARM_MOVT_ABS:
|
||||
inst = TO_NATIVE(*(uint32_t *)loc);
|
||||
inst = get_unaligned_native((uint32_t *)loc);
|
||||
offset = sign_extend32(((inst & 0xf0000) >> 4) | (inst & 0xfff),
|
||||
15);
|
||||
return offset + sym->st_value;
|
||||
case R_ARM_PC24:
|
||||
case R_ARM_CALL:
|
||||
case R_ARM_JUMP24:
|
||||
inst = TO_NATIVE(*(uint32_t *)loc);
|
||||
inst = get_unaligned_native((uint32_t *)loc);
|
||||
offset = sign_extend32((inst & 0x00ffffff) << 2, 25);
|
||||
return offset + sym->st_value + 8;
|
||||
case R_ARM_THM_MOVW_ABS_NC:
|
||||
case R_ARM_THM_MOVT_ABS:
|
||||
upper = TO_NATIVE(*(uint16_t *)loc);
|
||||
lower = TO_NATIVE(*((uint16_t *)loc + 1));
|
||||
upper = get_unaligned_native((uint16_t *)loc);
|
||||
lower = get_unaligned_native((uint16_t *)loc + 1);
|
||||
offset = sign_extend32(((upper & 0x000f) << 12) |
|
||||
((upper & 0x0400) << 1) |
|
||||
((lower & 0x7000) >> 4) |
|
||||
@@ -1195,8 +1195,8 @@ static Elf_Addr addend_arm_rel(void *loc, Elf_Sym *sym, unsigned int r_type)
|
||||
* imm11 = lower[10:0]
|
||||
* imm32 = SignExtend(S:J2:J1:imm6:imm11:'0')
|
||||
*/
|
||||
upper = TO_NATIVE(*(uint16_t *)loc);
|
||||
lower = TO_NATIVE(*((uint16_t *)loc + 1));
|
||||
upper = get_unaligned_native((uint16_t *)loc);
|
||||
lower = get_unaligned_native((uint16_t *)loc + 1);
|
||||
|
||||
sign = (upper >> 10) & 1;
|
||||
j1 = (lower >> 13) & 1;
|
||||
@@ -1219,8 +1219,8 @@ static Elf_Addr addend_arm_rel(void *loc, Elf_Sym *sym, unsigned int r_type)
|
||||
* I2 = NOT(J2 XOR S)
|
||||
* imm32 = SignExtend(S:I1:I2:imm10:imm11:'0')
|
||||
*/
|
||||
upper = TO_NATIVE(*(uint16_t *)loc);
|
||||
lower = TO_NATIVE(*((uint16_t *)loc + 1));
|
||||
upper = get_unaligned_native((uint16_t *)loc);
|
||||
lower = get_unaligned_native((uint16_t *)loc + 1);
|
||||
|
||||
sign = (upper >> 10) & 1;
|
||||
j1 = (lower >> 13) & 1;
|
||||
@@ -1241,7 +1241,7 @@ static Elf_Addr addend_mips_rel(uint32_t *location, unsigned int r_type)
|
||||
{
|
||||
uint32_t inst;
|
||||
|
||||
inst = TO_NATIVE(*location);
|
||||
inst = get_unaligned_native(location);
|
||||
switch (r_type) {
|
||||
case R_MIPS_LO16:
|
||||
return inst & 0xffff;
|
||||
|
||||
Reference in New Issue
Block a user