How can I write machine code into RAM and then execute it?

johnsondavies
Posts: 4
Joined: Thu Oct 11, 2018 6:10 pm

How can I write machine code into RAM and then execute it?

Postby johnsondavies » Sat Jul 17, 2021 3:33 pm

I want to write RISC-V machine code instructions to RAM from a program on an ESP32-C3-DevKitM-1 and then execute them.

If I define my code area as:

Code: Select all

uint8_t MyCode[64];
then I get the following error when I try to execute the machine code:

Guru Meditation Error: Core 0 panic'ed (Instruction access fault). Exception was unhandled.

If I define my code as:

Code: Select all

IRAM_ATTR uint8_t MyCode[64];
I get the following error when I try to write to it:

Guru Meditation Error: Core 0 panic'ed (Memory protection fault).
memory type: IRAM0_SRAM
faulting address: 0x40380210
world: 0
operation type: X

Is there a RAM attribute that will allow me to both write to it and execute it, or any other suggestions?

johnsondavies
Posts: 4
Joined: Thu Oct 11, 2018 6:10 pm

Re: How can I write machine code into RAM and then execute it?

Postby johnsondavies » Thu Jul 22, 2021 3:33 pm

Here's a bit more information about what I want to do, in the hope that it will enable someone to offer a solution.

The following test program puts a RISC-V machine-code program into RAM:
  1. #define WORDALIGNED __attribute__((aligned (8)))
  2.  
  3. IRAM_ATTR uint8_t MyCode[64] WORDALIGNED = { 0xb5, 0x45, 0x33, 0x05, 0xb5, 0x02, 0x82, 0x80 };
  4. //                                           li a1,13    mul a0,a0,a1            ret
  5.  
  6. typedef int (*intfn_ptr_type)(int x);
  7.  
  8. int test (int x) {
  9.   // MyCode[0] = 0xb5;
  10.   return ((intfn_ptr_type)&MyCode[0])(x);
  11. }
  12.  
  13. void setup() {
  14.   Serial.begin(9600);
  15.   delay(5000);
  16.   Serial.println(test(11));
  17.   Serial.println("End");
  18. }
  19.  
  20. void loop() {
  21. }
It executes the following RISC-V machine-code program:

li a1,13
mul a0,a0,a1
ret

which multiplies the first parameter, in a0, by 13. Running the program passes the parameter 11 and gives the following output:

143
End

This works fine for machine-code known at compile time, but I want to be able to generate the machine code at run time; for example, by prompting the user for it. You can simulate this by uncommenting the line:

// MyCode[0] = 0xb5;

but this then crashes with the error as mentioned above:

Guru Meditation Error: Core 0 panic'ed (Memory protection fault).
memory type: IRAM0_SRAM
faulting address: 0x40380210
world: 0
operation type: X

Any suggestions welcomed.

Thank you, David

ESP_Sprite
Posts: 9730
Joined: Thu Nov 26, 2015 4:08 am

Re: How can I write machine code into RAM and then execute it?

Postby ESP_Sprite » Fri Jul 23, 2021 3:08 am

This is caused by the memory protection of ESP-IDF: it assumes all executable code comes from the project binary, and that an attempt to re-write code or to execute data is someone maliciously trying to break into the system, and as such needs to be stopped. As you found out, it's pretty good at doing exactly that.

In ESP-IDF, this memory protection thing can be turned off in menuconfig (Component config → ESP System Settings → Memory protection), however in Arduino, you may need to recompile the ESP-IDF libraries to get the same effect: Because allowing it would be a security risk, aside from a full processor reset there is no way to disable the memory protection at runtime once it's set.

johnsondavies
Posts: 4
Joined: Thu Oct 11, 2018 6:10 pm

Re: How can I write machine code into RAM and then execute it?

Postby johnsondavies » Sat Jul 24, 2021 8:14 pm

Hi @ESP_Sprite,

Thank you for your reply; that confirms what I suspected. However, I really need a solution that will work for users with the standard Arduino core, so recompiling the ESP-IDF libraries isn't really possible.

How about if I copied the machine code from RAM to Flash memory, and then executed it from there. Would that work?

If so, what would be the easiest way to copy it to Flash, at a fixed memory address?

Thank you, David

ESP_Sprite
Posts: 9730
Joined: Thu Nov 26, 2015 4:08 am

Re: How can I write machine code into RAM and then execute it?

Postby ESP_Sprite » Mon Jul 26, 2021 2:09 am

I think that could work, however you would need to make sure to overwrite a region in flash that already is marked as executable, otherwise you'll run into the same issue.

Who is online

Users browsing this forum: No registered users and 54 guests