MN10300: Add support for new ELF relocs in kernel modules
Add support for new relocs which may show up in MN10300 kernel modules due to linker relaxation. Signed-off-by: Mark Salter <msalter@redhat.com> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
d282922461
commit
5ae8606d57
|
@ -28,6 +28,8 @@
|
||||||
#define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */
|
#define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */
|
||||||
#define R_MN10300_24 9 /* Direct 24 bit. */
|
#define R_MN10300_24 9 /* Direct 24 bit. */
|
||||||
#define R_MN10300_RELATIVE 23 /* Adjust by program base. */
|
#define R_MN10300_RELATIVE 23 /* Adjust by program base. */
|
||||||
|
#define R_MN10300_SYM_DIFF 33 /* Adjustment when relaxing. */
|
||||||
|
#define R_MN10300_ALIGN 34 /* Alignment requirement. */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ELF register definitions..
|
* ELF register definitions..
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* MN10300 Kernel module helper routines
|
/* MN10300 Kernel module helper routines
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007, 2008 Red Hat, Inc. All Rights Reserved.
|
* Copyright (C) 2007, 2008, 2009 Red Hat, Inc. All Rights Reserved.
|
||||||
* Written by Mark Salter (msalter@redhat.com)
|
* Written by Mark Salter (msalter@redhat.com)
|
||||||
* - Derived from arch/i386/kernel/module.c
|
* - Derived from arch/i386/kernel/module.c
|
||||||
*
|
*
|
||||||
|
@ -103,10 +103,10 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
|
||||||
unsigned int relsec,
|
unsigned int relsec,
|
||||||
struct module *me)
|
struct module *me)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i, sym_diff_seen = 0;
|
||||||
Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
|
Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
|
||||||
Elf32_Sym *sym;
|
Elf32_Sym *sym;
|
||||||
Elf32_Addr relocation;
|
Elf32_Addr relocation, sym_diff_val = 0;
|
||||||
uint8_t *location;
|
uint8_t *location;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
|
|
||||||
|
@ -126,6 +126,22 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
|
||||||
/* this is the adjustment to be made */
|
/* this is the adjustment to be made */
|
||||||
relocation = sym->st_value + rel[i].r_addend;
|
relocation = sym->st_value + rel[i].r_addend;
|
||||||
|
|
||||||
|
if (sym_diff_seen) {
|
||||||
|
switch (ELF32_R_TYPE(rel[i].r_info)) {
|
||||||
|
case R_MN10300_32:
|
||||||
|
case R_MN10300_24:
|
||||||
|
case R_MN10300_16:
|
||||||
|
case R_MN10300_8:
|
||||||
|
relocation -= sym_diff_val;
|
||||||
|
sym_diff_seen = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printk(KERN_ERR "module %s: Unexpected SYM_DIFF relocation: %u\n",
|
||||||
|
me->name, ELF32_R_TYPE(rel[i].r_info));
|
||||||
|
return -ENOEXEC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (ELF32_R_TYPE(rel[i].r_info)) {
|
switch (ELF32_R_TYPE(rel[i].r_info)) {
|
||||||
/* for the first four relocation types, we simply
|
/* for the first four relocation types, we simply
|
||||||
* store the adjustment at the location given */
|
* store the adjustment at the location given */
|
||||||
|
@ -157,12 +173,29 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
|
||||||
*location = relocation - (uint32_t) location;
|
*location = relocation - (uint32_t) location;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case R_MN10300_SYM_DIFF:
|
||||||
|
/* This is used to adjust the next reloc as required
|
||||||
|
* by relaxation. */
|
||||||
|
sym_diff_seen = 1;
|
||||||
|
sym_diff_val = sym->st_value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case R_MN10300_ALIGN:
|
||||||
|
/* Just ignore the ALIGN relocs.
|
||||||
|
* Only interesting if kernel performed relaxation. */
|
||||||
|
continue;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printk(KERN_ERR "module %s: Unknown relocation: %u\n",
|
printk(KERN_ERR "module %s: Unknown relocation: %u\n",
|
||||||
me->name, ELF32_R_TYPE(rel[i].r_info));
|
me->name, ELF32_R_TYPE(rel[i].r_info));
|
||||||
return -ENOEXEC;
|
return -ENOEXEC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (sym_diff_seen) {
|
||||||
|
printk(KERN_ERR "module %s: Nothing follows SYM_DIFF relocation: %u\n",
|
||||||
|
me->name, ELF32_R_TYPE(rel[i].r_info));
|
||||||
|
return -ENOEXEC;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue