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.
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 ... ?
Under particular circumstances when using valid inline assembler, the compiler may cause the emission of relocations which cause the module loader to barf in a similar way to what you saw, but I don't know if this is what is biting you. This is relatively rare though, affecting the use of some low-level macro from <asm/uaccess.h> in loadable modules.
See
ARM: Thumb-2: Relax relocation requirements for non-function symbols http://article.gmane.org/gmane.linux.ports.arm.kernel/116054/
This might be what you were remembering. I'll follow up and repost this, but I plan to wait for the merge window to close first, since it's not top priority.
Cheers ---Dave
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.
Under particular circumstances when using valid inline assembler, the compiler may cause the emission of relocations which cause the module loader to barf in a similar way to what you saw, but I don't know if this is what is biting you. This is relatively rare though, affecting the use of some low-level macro from <asm/uaccess.h> in loadable modules.
See
ARM: Thumb-2: Relax relocation requirements for non-function symbols http://article.gmane.org/gmane.linux.ports.arm.kernel/116054/
This might be what you were remembering.
Yes, that's what I remembered.
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
On Tue, 2011-05-24 at 17:54 +0100, Dave Martin wrote:
On Tue, May 24, 2011 at 04:30:23PM +0100, Tixy wrote:
[...]
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::.
My jump is semantically the same as a function call, because execution eventually returns back to just after the branch instruction.
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.
I think this is the situation, foo() is called from a module_init function, bar() is non-static so it doesn't get optimised out leaving label bar2 undefeined.
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.
The code in question is my module for testing kprobes. I have macros create test cases for probing different CPU instructions, each test case generates inline assembler.
void foo(void) { TEST("instruction_to_test1") TEST("instruction_to_test2") ... }
Each TEST expands to something like
__asm__ __volatile__ ( "bl __test_case_start \n\t" ".word some, inline, data \n\t" ".code "TEST_ISA" \n\t" "0: \n\t" "instruction_to_test \n\t" "b __test_case_end_"TEST_ISA" \n\t" ".align \n\t" ".code "NORMAL_ISA" \n\t" "99: \n\t" );
The __test_case_start and __test_case_end labels are test framework code written as inline assembler in another C function, i.e. bar() in my original example.
The TEST_ISA macro expands to '32' or '16' depending on whether I'm testing ARM or Thumb instructions, and NORMAL_ISA is 32 for ARM kernels and 16 for Thumb2 kernels.
The __test_case_end function iterates the test case several times by jumping back to label 0: and finishes by jumping back to label 99:
On Wed, May 25, 2011 at 10:17:23AM +0100, Tixy wrote:
On Tue, 2011-05-24 at 17:54 +0100, Dave Martin wrote:
On Tue, May 24, 2011 at 04:30:23PM +0100, Tixy wrote:
[...]
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::.
My jump is semantically the same as a function call, because execution eventually returns back to just after the branch instruction.
Well yeees, you will get away with it. The compiler really isn't designed to cope with this sort of thing, though.
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.
I think this is the situation, foo() is called from a module_init function, bar() is non-static so it doesn't get optimised out leaving label bar2 undefeined.
OK, that sounds like the explanation for the specific issue seen anyway. In which case adding .type is correct (note that adding this is always harmless anyway).
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.
The code in question is my module for testing kprobes. I have macros create test cases for probing different CPU instructions, each test case generates inline assembler.
void foo(void) { TEST("instruction_to_test1") TEST("instruction_to_test2") ... }
Each TEST expands to something like
__asm__ __volatile__ ( "bl __test_case_start \n\t" ".word some, inline, data \n\t"
.word doesn't implicitly align to a word boundary in Thumb, so you may need .align before it.
.word in inline asm may cause branch fixup errors in the code generated by the compiler, since the compiler has to guesstimate the size of output code generate by the asm block. Data directives, assembler macro expansion, .align and ISA changes can all throw this estimate off.
In practice one tends to get away with this however: gcc assumes every instruction might expand to 32 bits even for Thumb-2.
For .word, it's therefore better not to declare more than one item per statement. (For .quad, .double etc., you just lose ... eventually)
".code "TEST_ISA" \n\t"
From some conversations with tools guys, I remember that .arm/.thumb are
preferred to ".code". You could generate this easily of TEST_ISA and NORMAL_ISA are defined to "arm" and "thumb" instead of "32" and "16".
It's a minor thing though ... in reality I expect .code will continue to be understood by the assembler forever in any case.
"0: \n\t" "instruction_to_test \n\t" "b __test_case_end_"TEST_ISA" \n\t" ".align \n\t"
(Actually, you don't need .align here, but it's harmless. Unlike data, every instruction emitted by the assembler is always aligned up to the appropriate boundary depending on the ISA.)
".code "NORMAL_ISA" \n\t" "99: \n\t" );
The __test_case_start and __test_case_end labels are test framework code written as inline assembler in another C function, i.e. bar() in my original example.
The TEST_ISA macro expands to '32' or '16' depending on whether I'm testing ARM or Thumb instructions, and NORMAL_ISA is 32 for ARM kernels and 16 for Thumb2 kernels.
The __test_case_end function iterates the test case several times by jumping back to label 0: and finishes by jumping back to label 99:
I see no C code except for void foo(void), __asm__ __volatile__, some brackets and a lot of quote marks and backslashes, though I appreciate we don't have the whole file here.
Is there any reason why this shouldn't be coded in out-of-line assembler instead? Then, most of the "how do I smuggle this past the compiler" issues would just go away.
Cheers ---Dave
On Wed, 2011-05-25 at 14:51 +0100, Dave Martin wrote:
On Wed, May 25, 2011 at 10:17:23AM +0100, Tixy wrote:
The code in question is my module for testing kprobes. I have macros create test cases for probing different CPU instructions, each test case generates inline assembler.
void foo(void) { TEST("instruction_to_test1") TEST("instruction_to_test2") ... }
Each TEST expands to something like
__asm__ __volatile__ ( "bl __test_case_start \n\t" ".word some, inline, data \n\t"
.word doesn't implicitly align to a word boundary in Thumb, so you may need .align before it.
In reality, there's more than just .word statements, there's data structures built up with more macros generating .byte, .short, .word and .ascii. Trust me, I have all alignment issues sorted :-)
.word in inline asm may cause branch fixup errors in the code generated by the compiler, since the compiler has to guesstimate the size of output code generate by the asm block. Data directives, assembler macro expansion, .align and ISA changes can all throw this estimate off.
In practice one tends to get away with this however: gcc assumes every instruction might expand to 32 bits even for Thumb-2.
For .word, it's therefore better not to declare more than one item per statement. (For .quad, .double etc., you just lose ... eventually)
".code "TEST_ISA" \n\t"
From some conversations with tools guys, I remember that .arm/.thumb are preferred to ".code". You could generate this easily of TEST_ISA and NORMAL_ISA are defined to "arm" and "thumb" instead of "32" and "16".
I switched to .code so I could store TEST_ISA as a numerical flag in my data structures, I could easily change though.
It's a minor thing though ... in reality I expect .code will continue to be understood by the assembler forever in any case.
"0: \n\t" "instruction_to_test \n\t" "b __test_case_end_"TEST_ISA" \n\t" ".align \n\t"
(Actually, you don't need .align here, but it's harmless. Unlike data, every instruction emitted by the assembler is always aligned up to the appropriate boundary depending on the ISA.)
I do need the align because otherwise the label 99: below won't be aligned, and that's the label test_case_end jumps back to.
".code "NORMAL_ISA" \n\t" "99: \n\t" );
The __test_case_start and __test_case_end labels are test framework code written as inline assembler in another C function, i.e. bar() in my original example.
The TEST_ISA macro expands to '32' or '16' depending on whether I'm testing ARM or Thumb instructions, and NORMAL_ISA is 32 for ARM kernels and 16 for Thumb2 kernels.
The __test_case_end function iterates the test case several times by jumping back to label 0: and finishes by jumping back to label 99:
I see no C code except for void foo(void), __asm__ __volatile__, some brackets and a lot of quote marks and backslashes, though I appreciate we don't have the whole file here.
Is there any reason why this shouldn't be coded in out-of-line assembler instead? Then, most of the "how do I smuggle this past the compiler" issues would just go away.
test_case_{start,end} are mostly trampolines which call C code, but the functions containing the test cases themselves do just expand to asm statements. However, I make heavy use of macro expansion and string literal concatenation to paste together assembler instructions, I'm not sure I could do all of this in an assembler file. Anyway, I'd rather not redo weeks of work unless things are very broken.
On Wed, May 25, 2011 at 04:02:40PM +0100, Tixy wrote:
On Wed, 2011-05-25 at 14:51 +0100, Dave Martin wrote:
On Wed, May 25, 2011 at 10:17:23AM +0100, Tixy wrote:
The code in question is my module for testing kprobes. I have macros create test cases for probing different CPU instructions, each test case generates inline assembler.
Can this test module go into the kernel tree? Nico might have a view on whether that's likely to be useful.
Although we're focusing on ARM, I also wonder whether anything here is generalisable to other arches -- if so, upstream might be correspondingly more interested. This might be hard to achieve with this sort of tests, though.
void foo(void) { TEST("instruction_to_test1") TEST("instruction_to_test2") ... }
Each TEST expands to something like
__asm__ __volatile__ ( "bl __test_case_start \n\t" ".word some, inline, data \n\t"
.word doesn't implicitly align to a word boundary in Thumb, so you may need .align before it.
In reality, there's more than just .word statements, there's data structures built up with more macros generating .byte, .short, .word and .ascii. Trust me, I have all alignment issues sorted :-)
OK, I'll judge that based on the final code ;)
.word in inline asm may cause branch fixup errors in the code generated by the compiler, since the compiler has to guesstimate the size of output code generate by the asm block. Data directives, assembler macro expansion, .align and ISA changes can all throw this estimate off.
In practice one tends to get away with this however: gcc assumes every instruction might expand to 32 bits even for Thumb-2.
For .word, it's therefore better not to declare more than one item per statement. (For .quad, .double etc., you just lose ... eventually)
".code "TEST_ISA" \n\t"
From some conversations with tools guys, I remember that .arm/.thumb are preferred to ".code". You could generate this easily of TEST_ISA and NORMAL_ISA are defined to "arm" and "thumb" instead of "32" and "16".
I switched to .code so I could store TEST_ISA as a numerical flag in my data structures, I could easily change though.
Doesn't feel too important. If the assembler stops liking it one day, we'll get obvious assembly-time errors which will be easy to fix. But that's an unlikely eventuality anyhow...
It's a minor thing though ... in reality I expect .code will continue to be understood by the assembler forever in any case.
"0: \n\t" "instruction_to_test \n\t" "b __test_case_end_"TEST_ISA" \n\t" ".align \n\t"
(Actually, you don't need .align here, but it's harmless. Unlike data, every instruction emitted by the assembler is always aligned up to the appropriate boundary depending on the ISA.)
I do need the align because otherwise the label 99: below won't be aligned, and that's the label test_case_end jumps back to.
I may just be getting confused by what the complete code does.
Do you have the whole thing committed somewhere? I could take a look if so.
".code "NORMAL_ISA" \n\t" "99: \n\t" );
The __test_case_start and __test_case_end labels are test framework code written as inline assembler in another C function, i.e. bar() in my original example.
The TEST_ISA macro expands to '32' or '16' depending on whether I'm testing ARM or Thumb instructions, and NORMAL_ISA is 32 for ARM kernels and 16 for Thumb2 kernels.
The __test_case_end function iterates the test case several times by jumping back to label 0: and finishes by jumping back to label 99:
I see no C code except for void foo(void), __asm__ __volatile__, some brackets and a lot of quote marks and backslashes, though I appreciate we don't have the whole file here.
Is there any reason why this shouldn't be coded in out-of-line assembler instead? Then, most of the "how do I smuggle this past the compiler" issues would just go away.
test_case_{start,end} are mostly trampolines which call C code, but the functions containing the test cases themselves do just expand to asm statements. However, I make heavy use of macro expansion and string literal concatenation to paste together assembler instructions, I'm not sure I could do all of this in an assembler file. Anyway, I'd rather not redo weeks of work unless things are very broken.
Assembler files are processed by cpp anyway, so anything that can be done in a C source file can be done there. We also have some useful facilities in <arm/assembler.h> for standalone assembler files, most of which are not easily usable in inline assembler (such as the BSYM macro for taking the address of code symbols so that indirect calls will work in ARM and Thumb) -- plus you can use assembler macros, which are almost infinitely more useful than the C preprocessor IMHO ... but that's just my personal hobby-horse ;)
Point taken though -- if you have something that works already, there's no need to rewrite everything. From snippets of code, I thought you were in the early stages of writing this.
Cheers ---Dave
On Wed, 2011-05-25 at 18:38 +0100, Dave Martin wrote:
On Wed, May 25, 2011 at 04:02:40PM +0100, Tixy wrote:
On Wed, 2011-05-25 at 14:51 +0100, Dave Martin wrote:
On Wed, May 25, 2011 at 10:17:23AM +0100, Tixy wrote:
The code in question is my module for testing kprobes. I have macros create test cases for probing different CPU instructions, each test case generates inline assembler.
Can this test module go into the kernel tree?
Yes.
Nico might have a view on whether that's likely to be useful.
He suggested it go in the kernel tree when I asked him ;-)
Although we're focusing on ARM, I also wonder whether anything here is generalisable to other arches -- if so, upstream might be correspondingly more interested. This might be hard to achieve with this sort of tests, though.
Most of it is very ARM specific.
It's a minor thing though ... in reality I expect .code will continue to be understood by the assembler forever in any case.
"0: \n\t" "instruction_to_test \n\t" "b __test_case_end_"TEST_ISA" \n\t" ".align \n\t"
(Actually, you don't need .align here, but it's harmless. Unlike data, every instruction emitted by the assembler is always aligned up to the appropriate boundary depending on the ISA.)
I do need the align because otherwise the label 99: below won't be aligned, and that's the label test_case_end jumps back to.
I may just be getting confused by what the complete code does.
Do you have the whole thing committed somewhere? I could take a look if so.
I put my latest code at http://tixy.me.uk/kprobes-test.c it needs some tidying up, documentation, and integrating into the kernel.
test_case_{start,end} are mostly trampolines which call C code, but the functions containing the test cases themselves do just expand to asm statements. However, I make heavy use of macro expansion and string literal concatenation to paste together assembler instructions, I'm not sure I could do all of this in an assembler file. Anyway, I'd rather not redo weeks of work unless things are very broken.
Assembler files are processed by cpp anyway, so anything that can be done in a C source file can be done there.
String concatenation isn't a CPP thing though is it? E.g. can I build a single assembler statement from strings? E.g. this artificial but realistic example macro
#define FOO(A,B) "add" A " r"__sringify(C) ", #99"
When used as FOO("s",0) produces an "adds r0, #99" instruction to assemble.
We also have some useful facilities in <arm/assembler.h> for standalone assembler files, most of which are not easily usable in inline assembler (such as the BSYM macro for taking the address of code symbols so that indirect calls will work in ARM and Thumb) -- plus you can use assembler macros, which are almost infinitely more useful than the C preprocessor IMHO ... but that's just my personal hobby-horse ;)
Point taken though -- if you have something that works already, there's no need to rewrite everything. From snippets of code, I thought you were in the early stages of writing this.
The test code is essentially complete, I wrote it in parallel with the fixing and implementation of the instruction simulation.
On Wed, May 25, 2011 at 09:02:55PM +0100, Tixy wrote:
On Wed, 2011-05-25 at 18:38 +0100, Dave Martin wrote:
On Wed, May 25, 2011 at 04:02:40PM +0100, Tixy wrote:
On Wed, 2011-05-25 at 14:51 +0100, Dave Martin wrote:
On Wed, May 25, 2011 at 10:17:23AM +0100, Tixy wrote:
The code in question is my module for testing kprobes. I have macros create test cases for probing different CPU instructions, each test case generates inline assembler.
Can this test module go into the kernel tree?
Yes.
Nico might have a view on whether that's likely to be useful.
He suggested it go in the kernel tree when I asked him ;-)
Although we're focusing on ARM, I also wonder whether anything here is generalisable to other arches -- if so, upstream might be correspondingly more interested. This might be hard to achieve with this sort of tests, though.
Most of it is very ARM specific.
OK, fair enough.
It's a minor thing though ... in reality I expect .code will continue to be understood by the assembler forever in any case.
"0: \n\t" "instruction_to_test \n\t" "b __test_case_end_"TEST_ISA" \n\t" ".align \n\t"
(Actually, you don't need .align here, but it's harmless. Unlike data, every instruction emitted by the assembler is always aligned up to the appropriate boundary depending on the ISA.)
I do need the align because otherwise the label 99: below won't be aligned, and that's the label test_case_end jumps back to.
I may just be getting confused by what the complete code does.
Do you have the whole thing committed somewhere? I could take a look if so.
I put my latest code at http://tixy.me.uk/kprobes-test.c it needs some tidying up, documentation, and integrating into the kernel.
Thanks
test_case_{start,end} are mostly trampolines which call C code, but the functions containing the test cases themselves do just expand to asm statements. However, I make heavy use of macro expansion and string literal concatenation to paste together assembler instructions, I'm not sure I could do all of this in an assembler file. Anyway, I'd rather not redo weeks of work unless things are very broken.
Assembler files are processed by cpp anyway, so anything that can be done in a C source file can be done there.
String concatenation isn't a CPP thing though is it? E.g. can I build a single assembler statement from strings? E.g. this artificial but realistic example macro
#define FOO(A,B) "add" A " r"__sringify(C) ", #99"
When used as FOO("s",0) produces an "adds r0, #99" instruction to assemble.
In assembler almost nothing is quoted, so you can just use token- pasting:
#define HASH # #define FOO(A,B) add##A r##B, HASH 99
(admittedly the HASH thing is unfortunate, resulting from ARM assembler happening to use a symbol that's also a C preprocessor operator. There might be a better way of solving that.)
This would be referenced with A unquoted, i.e., FOO(s, 0)
Alternatively you can do it with an asembler macro:
.macro FOO A, B add\A r\B , #99 .endm
...
FOO s, 0
Cheers ---Dave
linaro-kernel@lists.linaro.org