3

Im trying to remove the stack dependency from the following code.

void  myfunction(struct kprobe *p, struct pt_regs *regs)
 {
         register void *rregs asm("r1") = regs;
         register void *rfn asm("lr") = p->ainsn.insn_fn;

         __asm__ __volatile__ (
                 "stmdb  sp!, {%[regs], r11}     \n\t"
                 "ldmia  %[regs], {r0-r12}       \n\t"    
                 "blx    %[fn]                   \n\t"
                 "ldr    lr, [sp], #4            \n\t" /* lr = regs */
                 "stmia  lr, {r0-r12}            \n\t"
                 "ldr    r11, [sp], #4           \n\t"

                 : [regs] "=r" (rregs), [fn] "=r" (rfn)
                 : "" (rregs), "1" (rfn)
                 : "r0", "r2", "r3", "r4", "r5", "r6", "r7",
                   "r8", "r9", "r10", "r12", "memory", "cc"
                 );
 }

In the above function, stmdb sp!, {%[regs], r11} pushes r1 and r11 into stack and later it retrives.

In my case, I should avoid using stack here. so I rewrote

void myfunction(struct kprobe *p, struct pt_regs *regs)
{
        int r1_bk = 0, r11_bk = 0;
        register void *rregs asm("r1") = regs;
        register void *rfn asm("lr") = p->ainsn.insn_fn;
        register void *r1b_c asm("r1") = &r1_bk;
        register void *r11b_c asm("r11") = &r11_bk;    

      __asm__ __volatile__ (
                "ldr    %[r1b], r1      \n\t"
                "ldr    %[r11b], r11    \n\t"
                "ldmia  %[regs], {r0-r12}       \n\t"
                "blx    %[fn]                   \n\t"    
                "ldr    lr, %[r1b]              \n\t" /* lr = regs */
                "stmia  lr, {r0-r12}            \n\t"
                "ldr    r11, %[r11b]            \n\t"

                : [regs] "=r" (rregs), [fn] "=r" (rfn), [r1b] "=r" (r1b_c), [r11b] "=r" (r11b_c)
                : "0" (rregs), "1" (rfn)
                : "r0", "r2", "r3", "r4", "r5", "r6", "r7",
                  "r8", "r9", "r10", "r12", "memory", "cc"
                );
}

When I compile, following error Im getting.

/tmp/ccJMefdC.s: Assembler messages:
/tmp/ccJMefdC.s:579: Error: internal_relocation (type: OFFSET_IMM) not fixed up
/tmp/ccJMefdC.s:580: Error: internal_relocation (type: OFFSET_IMM) not fixed up
/tmp/ccJMefdC.s:583: Error: internal_relocation (type: OFFSET_IMM) not fixed up
/tmp/ccJMefdC.s:585: Error: internal_relocation (type: OFFSET_IMM) not fixed up

I refered here internal relocation not fixed up. but it doesn't give clear idea. Please share your knowledge regarding this.

Community
  • 1
  • 1
Jeyaram
  • 9,158
  • 7
  • 41
  • 63
  • I don't see you restoring r1, while I see you loading what was r1b in r14 (which is LR). Is that wanted? – Jekyll Nov 27 '13 at 09:03
  • r1b's content holds r1 value. see `"ldr %[r1b], r1"` – Jeyaram Nov 27 '13 at 09:05
  • I've seen that, I didn't see the "ldr r1, %[r1b]" to restore the original value, but that is not even done in the original code where only r11 is restored. So I think it won't change anything, sorry – Jekyll Nov 27 '13 at 09:20
  • It looks pretty wild. You declare some locals, where would you expect them to go? If you can manage to get that snippet compiled, and if you disassemble that afterwards you'll probably notice it uses stack anyway. This doesn't look like a leaf function, so you can't rely on just scratch registers easily. and your usage of r1 is probably wrong as well. – auselen Nov 27 '13 at 09:23
  • @auselen I also have same(i.e `You declare some locals, where would you expect them to go?`) doubt. somehow I need to avoid using sp as of now. Is it possible.?? – Jeyaram Nov 27 '13 at 09:27
  • Is this an exam question? – auselen Nov 27 '13 at 09:31
  • 2
    http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem – auselen Nov 27 '13 at 09:32
  • Looking better I don't understand also "register void *r1b_c asm("r1") = &r1_bk; register void *r11b_c asm("r11") = &r11_bk;" what do you want to achieve loading those addresses? where is regs recorded now? – Jekyll Nov 27 '13 at 09:34
  • @Jekyll Im trying to hold previous r1 and r11 values to those `r1_bk` and `r11_bk` variables. – Jeyaram Nov 27 '13 at 09:36
  • In my opinion you are doing the opposite so you are copying the address of r1_bk in r1 and naming the variable as rfn. – Jekyll Nov 27 '13 at 09:46
  • @Jekyll. thanks for your guidance. Let me check and come back. – Jeyaram Nov 27 '13 at 09:50
  • typo there ... wrote rfn, meant r1b_c – Jekyll Nov 27 '13 at 09:55

2 Answers2

4

Your inline asm call clobbers almost all registers and it is explicitly told to compiler via volatile directive that it shouldn't skip or try to move the call around to optimize register usage. This means compiler while producing the equivalent instructions for myfunction needs to save registers to somewhere before emitting that inline assembly.

Let me prove it to you:

$ cat asm_vol.c 
void f() {
    asm volatile("" : : : "r0", "r2", "r3", "r4", "r5", "r6", "r7",
                  "r8", "r9", "r10", "r12", "memory", "cc");
}
$ arm-linux-gnueabihf-gcc -c -O2 asm_vol.c
$ arm-linux-gnueabihf-objdump -d asm_vol.o

asm_vol.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <f>:
   0:   e92d 07f0   stmdb   sp!, {r4, r5, r6, r7, r8, r9, sl}
   4:   e8bd 07f0   ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl}
   8:   4770        bx  lr
   a:   bf00        nop
auselen
  • 27,577
  • 7
  • 73
  • 114
2

The reason for the error message is that ldr take register and a memory reference, you are providing the same register twice. The assembler then interprets the register name as a memory location, and therefore complains that it is not defined in the same file.

Since you have run out of registers you can only avoid stack use by using a global variable.

Timothy Baldwin
  • 3,551
  • 1
  • 14
  • 23