Lovis XII
Lovis XII

Reputation: 57

Inline assembly with branch

I got the following code :

    int *heap_x_test = (int*) malloc(4*sizeof(int));
    heap_x_test[0] =   0x00310033 ; // add  zero,sp,gp
    heap_x_test[1] =   0x008110b3 ; // sll  ra,sp,s0
    heap_x_test[2] =   0x00c00313 ; // li   t1,12
    heap_x_test[3] =   0x00f00493 ; // li   s1,15
    printk("Target adress is 0x%x\n",heap_x_test);
    printk("Code injection is 0x%x\n", heap_x_test[0]);
    __asm__("beq x0, x0, %0" : "i"(heap_x_test));

I try to send code inside the heap and make it execute. I use the pmp in a riscv implementation and i want to check if i setup it right to protect the heap.

This specific line of the code doesn't seem to work :

__asm__("beq x0, x0, %0" : "i"(heap_x_test));

I tried to modify "i" with "r" and "=r" but it doesn't work either, i also tried a jr instruction with heap_x_test as label in the asm macro but it doesn't seem to work either. The compiler return :

error: output operand constraint lacks '='
   37 |         __asm__("beq x0, x0, %0" : "i"(heap_x_test));

Edit : When i use "=r" it compile but in the objdump of main I don't see the beq instruction :

   0x80000ab0 <+0>: addi    sp,sp,-16
   0x80000ab4 <+4>: sw  ra,12(sp)
   0x80000ab8 <+8>: sw  s0,8(sp)
   0x80000abc <+12>:    li  a0,16
   0x80000ac0 <+16>:    jal ra,0x8000782c <malloc>
   0x80000ac4 <+20>:    mv  s0,a0
   0x80000ac8 <+24>:    lui a5,0x310
   0x80000acc <+28>:    addi    a5,a5,51 # 0x310033
   0x80000ad0 <+32>:    sw  a5,0(a0)
   0x80000ad4 <+36>:    lui a5,0x811
   0x80000ad8 <+40>:    addi    a5,a5,179 # 0x8110b3
   0x80000adc <+44>:    sw  a5,4(a0)
   0x80000ae0 <+48>:    lui a5,0xc00
   0x80000ae4 <+52>:    addi    a5,a5,787 # 0xc00313
   0x80000ae8 <+56>:    sw  a5,8(a0)
   0x80000aec <+60>:    lui a5,0xf00
   0x80000af0 <+64>:    addi    a5,a5,1171 # 0xf00493
   0x80000af4 <+68>:    sw  a5,12(a0)
   0x80000af8 <+72>:    mv  a1,a0
   0x80000afc <+76>:    lui a0,0x80008
   0x80000b00 <+80>:    addi    a0,a0,-588 # 0x80007db4
   0x80000b04 <+84>:    jal ra,0x80001340 <printk>
   0x80000b08 <+88>:    lw  a1,0(s0)
   0x80000b0c <+92>:    lui a0,0x80008
   0x80000b10 <+96>:    addi    a0,a0,-564 # 0x80007dcc
   0x80000b14 <+100>:   jal ra,0x80001340 <printk>
   0x80000b18 <+104>:   lw  ra,12(sp)
   0x80000b1c <+108>:   lw  s0,8(sp)
   0x80000b20 <+112>:   addi    sp,sp,16
   0x80000b24 <+116>:   ret

If i use volatile to avoid compiler optimisation it output :

undefined reference to `a5

Thanks by advance !

Upvotes: 0

Views: 346

Answers (2)

Lovis XII
Lovis XII

Reputation: 57

With all of what you suggested i finally succeed to write my code, here's a the correction of the code which seems to work just fine :


#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <zephyr/kernel.h>
#include <malloc.h>


 void dummy_function(){
    printk("Inside %s\n", __func__);
 }


void main(void)
{
    int buffer[12];
    int *heap_x_test = (int*) malloc(4*sizeof(int));
    heap_x_test[0] =   0x00310033 ; // add  zero,sp,gp
    heap_x_test[1] =   0x008110b3 ; // sll  ra,sp,s0
    heap_x_test[2] =   0x00c00313 ; // li   t1,12
    heap_x_test[3] =   0x00f00493 ; // li   s1,15
    printk("Target adress is 0x%x\n",heap_x_test);
    printk("Code injection is 0x%x\n", heap_x_test[0]);

    void (*dummy_function)()__attribute__((used)) = (void (*)())heap_x_test;
    dummy_function();

}

Kind regards

Upvotes: 0

Chris Dodd
Chris Dodd

Reputation: 126468

The target of a beq or other simple branch instruction needs to be a label in the code, not a value. In general, to jump to code in the heap, you're going to need an indirect branch. On riscv, the only way to do that is with a jalr instruction. Something like:

__asm__ volatile("jr %0" :: "r"(heap_x_test));

(jr being an alias for jalr with a fixed x0 destination)

Upvotes: 1

Related Questions