【问题标题】:Removing stack dependency from Assembly Code从汇编代码中删除堆栈依赖项
【发布时间】:2013-12-12 19:13:42
【问题描述】:

我正在尝试从以下代码中删除堆栈依赖项。

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"
                 );
 }

在上述函数中,stmdb sp!, {%[regs], r11}r1r11 压入堆栈,然后再返回。

就我而言,我应该避免在这里使用堆栈。所以我重写了

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"
                );
}

当我编译时,出现以下错误。

/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

我在这里提到了internal relocation not fixed up。但它没有给出明确的想法。请分享您对此的了解。

【问题讨论】:

  • 我没有看到您正在恢复 r1,而我看到您正在加载 r14 中的 r1b(即 LR)。这是想要的吗?
  • r1b 的内容包含 r1 值。见"ldr %[r1b], r1"
  • 我看到了,我没有看到 "ldr r1, %[r1b]" 恢复原始值,但是在仅恢复 r11 的原始代码中甚至没有这样做.所以我认为它不会改变任何东西,对不起
  • 看起来很狂野。你声明了一些本地人,你希望他们去哪里?如果您能够设法编译该 sn-p,并且如果您之后反汇编它,您可能会注意到它无论如何都使用堆栈。这看起来不像一个叶子函数,所以你不能轻易地依赖临时寄存器。并且您对 r1 的使用也可能是错误的。

标签: c assembly arm inline-assembly kprobe


【解决方案1】:

错误消息的原因是ldr 获取寄存器和内存引用,您提供了两次相同的寄存器。然后汇编器将寄存器名称解释为内存位置,因此抱怨它没有在同一个文件中定义。

由于您的寄存器已经用完,您只能通过使用全局变量来避免使用堆栈。

【讨论】:

    【解决方案2】:

    您的内联asm 调用破坏了几乎所有寄存器,并且通过volatile 指令明确告知编译器它不应跳过或尝试移动调用以优化寄存器使用。这意味着编译器在为 myfunction 生成等效指令时需要在发出该内联汇编之前将寄存器保存到某个位置。

    让我证明给你看:

    $ 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-18
      • 1970-01-01
      • 1970-01-01
      • 2019-10-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      • 2015-12-23
      相关资源
      最近更新 更多