[PATCH] ARM: kprobes: Fix build error in test code
Jon Medhurst (Tixy)
jon.medhurst at linaro.org
Wed Nov 9 05:36:15 EST 2011
On Wed, 2011-10-19 at 10:47 +0100, Jon Medhurst (Tixy) wrote:
> When compiling kprobes-test-thumb.c an error like below may occur:
>
> /tmp/ccKcuJcG.s:19179: Error: offset out of range
>
> This is caused by the compiler underestimating the size of the inline
> assembler instructions containing ".space 0x1000" and failing to spill
> the literal pool in time to prevent the generation of PC relative load
> instruction with invalid offsets.
>
> The fix implemented by this patch is to replace a single large .space
> directive by a number of 4 byte .space's. This requires splitting the
> macros which generate test cases for branch instructions into two forms:
> one with, and one without support for inserting extra code between
> branch and target.
>
> Signed-off-by: Jon Medhurst <jon.medhurst at linaro.org>
> ---
Nicolas, I noticed that you put this patch into the Linaro kernel tree,
can I take that as an Acked-by? ;-)
--
Tixy
> arch/arm/kernel/kprobes-test.h | 100 ++++++++++++++++++++++++----------
> arch/arm/kernel/kprobes-test-thumb.c | 16 +++---
> 2 files changed, 78 insertions(+), 38 deletions(-)
>
> diff --git a/arch/arm/kernel/kprobes-test.h b/arch/arm/kernel/kprobes-test.h
> index 0dc5d77..e28a869 100644
> --- a/arch/arm/kernel/kprobes-test.h
> +++ b/arch/arm/kernel/kprobes-test.h
> @@ -149,23 +149,31 @@ struct test_arg_end {
> "1: "instruction" \n\t" \
> " nop \n\t"
>
> -#define TEST_BRANCH_F(instruction, xtra_dist) \
> +#define TEST_BRANCH_F(instruction) \
> TEST_INSTRUCTION(instruction) \
> - ".if "#xtra_dist" \n\t" \
> " b 99f \n\t" \
> - ".space "#xtra_dist" \n\t" \
> - ".endif \n\t" \
> + "2: nop \n\t"
> +
> +#define TEST_BRANCH_B(instruction) \
> + " b 50f \n\t" \
> + " b 99f \n\t" \
> + "2: nop \n\t" \
> + " b 99f \n\t" \
> + TEST_INSTRUCTION(instruction)
> +
> +#define TEST_BRANCH_FX(instruction, codex) \
> + TEST_INSTRUCTION(instruction) \
> + " b 99f \n\t" \
> + codex" \n\t" \
> " b 99f \n\t" \
> "2: nop \n\t"
>
> -#define TEST_BRANCH_B(instruction, xtra_dist) \
> +#define TEST_BRANCH_BX(instruction, codex) \
> " b 50f \n\t" \
> " b 99f \n\t" \
> "2: nop \n\t" \
> " b 99f \n\t" \
> - ".if "#xtra_dist" \n\t" \
> - ".space "#xtra_dist" \n\t" \
> - ".endif \n\t" \
> + codex" \n\t" \
> TEST_INSTRUCTION(instruction)
>
> #define TESTCASE_END \
> @@ -301,47 +309,60 @@ struct test_arg_end {
> TESTCASE_START(code1 #reg1 code2) \
> TEST_ARG_PTR(reg1, val1) \
> TEST_ARG_END("") \
> - TEST_BRANCH_F(code1 #reg1 code2, 0) \
> + TEST_BRANCH_F(code1 #reg1 code2) \
> TESTCASE_END
>
> -#define TEST_BF_X(code, xtra_dist) \
> +#define TEST_BF(code) \
> TESTCASE_START(code) \
> TEST_ARG_END("") \
> - TEST_BRANCH_F(code, xtra_dist) \
> + TEST_BRANCH_F(code) \
> TESTCASE_END
>
> -#define TEST_BB_X(code, xtra_dist) \
> +#define TEST_BB(code) \
> TESTCASE_START(code) \
> TEST_ARG_END("") \
> - TEST_BRANCH_B(code, xtra_dist) \
> + TEST_BRANCH_B(code) \
> TESTCASE_END
>
> -#define TEST_BF_RX(code1, reg, val, code2, xtra_dist) \
> - TESTCASE_START(code1 #reg code2) \
> - TEST_ARG_REG(reg, val) \
> - TEST_ARG_END("") \
> - TEST_BRANCH_F(code1 #reg code2, xtra_dist) \
> +#define TEST_BF_R(code1, reg, val, code2) \
> + TESTCASE_START(code1 #reg code2) \
> + TEST_ARG_REG(reg, val) \
> + TEST_ARG_END("") \
> + TEST_BRANCH_F(code1 #reg code2) \
> TESTCASE_END
>
> -#define TEST_BB_RX(code1, reg, val, code2, xtra_dist) \
> - TESTCASE_START(code1 #reg code2) \
> - TEST_ARG_REG(reg, val) \
> - TEST_ARG_END("") \
> - TEST_BRANCH_B(code1 #reg code2, xtra_dist) \
> +#define TEST_BB_R(code1, reg, val, code2) \
> + TESTCASE_START(code1 #reg code2) \
> + TEST_ARG_REG(reg, val) \
> + TEST_ARG_END("") \
> + TEST_BRANCH_B(code1 #reg code2) \
> TESTCASE_END
>
> -#define TEST_BF(code) TEST_BF_X(code, 0)
> -#define TEST_BB(code) TEST_BB_X(code, 0)
> -
> -#define TEST_BF_R(code1, reg, val, code2) TEST_BF_RX(code1, reg, val, code2, 0)
> -#define TEST_BB_R(code1, reg, val, code2) TEST_BB_RX(code1, reg, val, code2, 0)
> -
> #define TEST_BF_RR(code1, reg1, val1, code2, reg2, val2, code3) \
> TESTCASE_START(code1 #reg1 code2 #reg2 code3) \
> TEST_ARG_REG(reg1, val1) \
> TEST_ARG_REG(reg2, val2) \
> TEST_ARG_END("") \
> - TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3, 0) \
> + TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3) \
> + TESTCASE_END
> +
> +#define TEST_BF_X(code, codex) \
> + TESTCASE_START(code) \
> + TEST_ARG_END("") \
> + TEST_BRANCH_FX(code, codex) \
> + TESTCASE_END
> +
> +#define TEST_BB_X(code, codex) \
> + TESTCASE_START(code) \
> + TEST_ARG_END("") \
> + TEST_BRANCH_BX(code, codex) \
> + TESTCASE_END
> +
> +#define TEST_BF_RX(code1, reg, val, code2, codex) \
> + TESTCASE_START(code1 #reg code2) \
> + TEST_ARG_REG(reg, val) \
> + TEST_ARG_END("") \
> + TEST_BRANCH_FX(code1 #reg code2, codex) \
> TESTCASE_END
>
> #define TEST_X(code, codex) \
> @@ -372,6 +393,25 @@ struct test_arg_end {
> TESTCASE_END
>
>
> +/*
> + * Macros for defining space directives spread over multiple lines.
> + * These are required so the compiler guesses better the length of inline asm
> + * code and will spill the literal pool early enough to avoid generating PC
> + * relative loads with out of range offsets.
> + */
> +#define TWICE(x) x x
> +#define SPACE_0x8 TWICE(".space 4\n\t")
> +#define SPACE_0x10 TWICE(SPACE_0x8)
> +#define SPACE_0x20 TWICE(SPACE_0x10)
> +#define SPACE_0x40 TWICE(SPACE_0x20)
> +#define SPACE_0x80 TWICE(SPACE_0x40)
> +#define SPACE_0x100 TWICE(SPACE_0x80)
> +#define SPACE_0x200 TWICE(SPACE_0x100)
> +#define SPACE_0x400 TWICE(SPACE_0x200)
> +#define SPACE_0x800 TWICE(SPACE_0x400)
> +#define SPACE_0x1000 TWICE(SPACE_0x800)
> +
> +
> /* Various values used in test cases... */
> #define N(val) (val ^ 0xffffffff)
> #define VAL1 0x12345678
> diff --git a/arch/arm/kernel/kprobes-test-thumb.c b/arch/arm/kernel/kprobes-test-thumb.c
> index 5e726c3..5d8b857 100644
> --- a/arch/arm/kernel/kprobes-test-thumb.c
> +++ b/arch/arm/kernel/kprobes-test-thumb.c
> @@ -222,8 +222,8 @@ void kprobe_thumb16_test_cases(void)
> DONT_TEST_IN_ITBLOCK(
> TEST_BF_R( "cbnz r",0,0, ", 2f")
> TEST_BF_R( "cbz r",2,-1,", 2f")
> - TEST_BF_RX( "cbnz r",4,1, ", 2f",0x20)
> - TEST_BF_RX( "cbz r",7,0, ", 2f",0x40)
> + TEST_BF_RX( "cbnz r",4,1, ", 2f", SPACE_0x20)
> + TEST_BF_RX( "cbz r",7,0, ", 2f", SPACE_0x40)
> )
> TEST_R("sxth r0, r",7, HH1,"")
> TEST_R("sxth r7, r",0, HH2,"")
> @@ -246,7 +246,7 @@ DONT_TEST_IN_ITBLOCK(
> TESTCASE_START(code) \
> TEST_ARG_PTR(13, offset) \
> TEST_ARG_END("") \
> - TEST_BRANCH_F(code,0) \
> + TEST_BRANCH_F(code) \
> TESTCASE_END
>
> TEST("push {r0}")
> @@ -319,8 +319,8 @@ CONDITION_INSTRUCTIONS(8,
>
> TEST_BF( "b 2f")
> TEST_BB( "b 2b")
> - TEST_BF_X("b 2f", 0x400)
> - TEST_BB_X("b 2b", 0x400)
> + TEST_BF_X("b 2f", SPACE_0x400)
> + TEST_BB_X("b 2b", SPACE_0x400)
>
> TEST_GROUP("Testing instructions in IT blocks")
>
> @@ -746,7 +746,7 @@ CONDITION_INSTRUCTIONS(22,
> TEST_BB("bne.w 2b")
> TEST_BF("bgt.w 2f")
> TEST_BB("blt.w 2b")
> - TEST_BF_X("bpl.w 2f",0x1000)
> + TEST_BF_X("bpl.w 2f", SPACE_0x1000)
> )
>
> TEST_UNSUPPORTED("msr cpsr, r0")
> @@ -786,11 +786,11 @@ CONDITION_INSTRUCTIONS(22,
>
> TEST_BF( "b.w 2f")
> TEST_BB( "b.w 2b")
> - TEST_BF_X("b.w 2f", 0x1000)
> + TEST_BF_X("b.w 2f", SPACE_0x1000)
>
> TEST_BF( "bl.w 2f")
> TEST_BB( "bl.w 2b")
> - TEST_BB_X("bl.w 2b", 0x1000)
> + TEST_BB_X("bl.w 2b", SPACE_0x1000)
>
> TEST_X( "blx __dummy_arm_subroutine",
> ".arm \n\t"
More information about the linux-arm-kernel
mailing list