On Tue, May 24, 2011 at 04:30:23PM +0100, Tixy wrote:
On Tue, 2011-05-24 at 15:57 +0100, Dave Martin wrote:
On Tue, May 24, 2011 at 02:43:54PM +0100, Tixy wrote:
Hi Dave
I've managed to reproduce a relocation error when loading a module built for Thumb. The runtime error message is:
section 4 reloc 247 sym '': relocation 30 out of range (0xbf9710c6 -> 0xbf96c000)
Relocation 30 is R_ARM_THM_JUMP24, and looking at apply_relocate() in arch/arm/kernel/module.c it looks like the error is caused by 'offset' being even here ...
/* only Thumb addresses allowed (no interworking) */ if (!(offset & 1) || offset <= (s32)0xff000000 || offset >= (s32)0x01000000) { pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", module->name, relindex, i, symname, ELF32_R_TYPE(rel->r_info), loc, sym->st_value); return -ENOEXEC; }
I seem to remember you posting some similar issue to a mailing list recently, or is my memory faulty?
I have some labels declared in inline assembler, and after adding
.type name_of_label, %function
the relocation error goes away, presumably because the label is now thumbified by having bit 0 set.
It's hard to judge whether that's right or wrong without the example, but most probably the module loader is doing the right thing, and the fix you suggest is probably also correct.
However, usually relocations wouldn't be generated against symbols in inline assmbler since most things can be fixed up locally; so I wonder if you're doing something "interesting" which needs special attention ... ?
The 'interesting' thing is branching from inline asm in a static function into inline asm in another non-static function. This test case reproduces it..
static void foo(void) { __asm__ __volatile__ ( "b bar2" ); }
void bar(void) { __asm__ __volatile__ ( "bar2:" ); }
As you say, neither the module loader or the toolchain seem to be doing anything wrong. The error is that the programmer (me) didn't provide the information that the label bar2 refers to a function. Adding the line ".type bar2, %function\n" before "bar2:" does this.
According to the gcc info docs, the above is wrong usage:
"Speaking of labels, jumps from one `asm' to another are not supported. The compiler's optimizers do not know about these jumps, and therefore they cannot take account of them when deciding how to optimize. *Note Extended asm with goto::.
I'm still not sure why you're getting a relocation (and hence a module loading error). One possibility is that the location of "b bar2" is in a different section from the label bar2; for example, foo() is called from an __init function, but bar() is part of the main module. Alternatively, gas might not be fixing the branch up at assembly time due to some range issue.
So, the .type directive is strictly speaking correct, but normally it's not needed when branching within a single file, unless the above conditions apply.
Either way, jumping from one function to another is doubtless a bad idea... is there a cleaner way to achieve what you're trying to do?
More context might be helpful if you want suggestions.
Cheers ---Dave