Commit 69ac5964 authored by Chaskiel Grundman's avatar Chaskiel Grundman Committed by Linus Torvalds

[PATCH] alpha: process_reloc_for_got confuses r_offset and r_addend

arch/alpha/kernel/module.c:process_reloc_for_got(), which figures out how big
the .got section for a module should be, appears to be confusing r_offset (the
file offset that the relocation needs to be applied to) with r_addend (the
offset of the relocation's actual target address from the address of the
relocation's symbol).  Because of this, one .got entry is allocated for each
relocation instead of one each unique symbol/addend.

In the module I am working with, this causes the .got section to be almost 10
times larger than it needs to be (75544 bytes instead of 7608 bytes).  As the
.got is accessed with global-pointer-relative instructions, it needs to be
within the 64k gp "zone", and a 75544 byte .got clearly does not fit.  The
result of this is that relocation overflows are detected during module load
and the load is aborted.

Change struct got_entry/process_reloc_for_got to fix this.
Acked-by: default avatarRichard Henderson <rth@twiddle.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 092c9488
...@@ -47,7 +47,7 @@ module_free(struct module *mod, void *module_region) ...@@ -47,7 +47,7 @@ module_free(struct module *mod, void *module_region)
struct got_entry { struct got_entry {
struct got_entry *next; struct got_entry *next;
Elf64_Addr r_offset; Elf64_Sxword r_addend;
int got_offset; int got_offset;
}; };
...@@ -57,14 +57,14 @@ process_reloc_for_got(Elf64_Rela *rela, ...@@ -57,14 +57,14 @@ process_reloc_for_got(Elf64_Rela *rela,
{ {
unsigned long r_sym = ELF64_R_SYM (rela->r_info); unsigned long r_sym = ELF64_R_SYM (rela->r_info);
unsigned long r_type = ELF64_R_TYPE (rela->r_info); unsigned long r_type = ELF64_R_TYPE (rela->r_info);
Elf64_Addr r_offset = rela->r_offset; Elf64_Sxword r_addend = rela->r_addend;
struct got_entry *g; struct got_entry *g;
if (r_type != R_ALPHA_LITERAL) if (r_type != R_ALPHA_LITERAL)
return; return;
for (g = chains + r_sym; g ; g = g->next) for (g = chains + r_sym; g ; g = g->next)
if (g->r_offset == r_offset) { if (g->r_addend == r_addend) {
if (g->got_offset == 0) { if (g->got_offset == 0) {
g->got_offset = *poffset; g->got_offset = *poffset;
*poffset += 8; *poffset += 8;
...@@ -74,7 +74,7 @@ process_reloc_for_got(Elf64_Rela *rela, ...@@ -74,7 +74,7 @@ process_reloc_for_got(Elf64_Rela *rela,
g = kmalloc (sizeof (*g), GFP_KERNEL); g = kmalloc (sizeof (*g), GFP_KERNEL);
g->next = chains[r_sym].next; g->next = chains[r_sym].next;
g->r_offset = r_offset; g->r_addend = r_addend;
g->got_offset = *poffset; g->got_offset = *poffset;
*poffset += 8; *poffset += 8;
chains[r_sym].next = g; chains[r_sym].next = g;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment