Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

how to get the bare bone compiled binary code of a C function?

I’m trying to implement an embedded firmware on an stm32 F4 micro that takes an binary code from the serial and execute it on the micro.

The idea is pretty simple of course the only tricky part is that since on the serial is complicate to send raw binary data I’m going to send everything through base64 encoding.

Here’s the code:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#include <Arduino.h>
#include <base64.hpp>

size_t read_serial_line(char *msg, size_t len, size_t timeout = 0) {
  const auto start = millis(); 
  size_t sz = 0;               

  do {
    while (not Serial.available()) {
      if (timeout > 0 and millis() > start + timeout) {
        return -1;
      }
    }

    msg[sz] = Serial.read();

    if (msg[sz] == '\r') {
      msg[sz] = '\0'; // replacing the end line with the end string

      // the next char must be a \n char since the Serial.println of arduino
      // works like that
      while (Serial.read() != '\n')
        ; // I discard it

      // now sz contains the length of the string as returned by strlen
      break; // end of line
    }

    if (timeout > 0 and millis() > start + timeout) {
      return -1;
    }
  } while (++sz < len);

  return sz; 
}

void setup() {
  Serial.begin(9600);

  Serial.println("begin!");
}

void loop() {
  char *msg = new char[2048](); // big line

  auto sz = read_serial_line(msg, 2048);

  Serial.print("\tlooping...");
  Serial.println(sz);
  Serial.print("received: ");
  Serial.println(msg);

  uint8_t *code = new uint8_t[2048]();

  sz = decode_base64(msg, code);

  Serial.println(sz);

  delay(1000);

  int (*code_fn)() = (int (*)())code;

  int c = code_fn();

  Serial.println(c);

  delete code;
  delete msg;
  delay(1000);
}

The next problem is to be able to compile and get the compiled binary code from this simple C function:

int fn() {
   return 3;
}

Here you can see the assembly of this stupid function.

I tried, of course using the same tool chain used for the main code of the micro, to compile it with gcc using the option for the position independent code and then I tried to copy the .text secion with objcopy, to finish I took the text returned from the xxd command, I encoded it in base64 and I sent it to the micro.

here are the commands that I used:

$ arm-none-eabi-gcc -fPIC -c test.c
$ arm-none-eabi-objcopy -j .text test.o test.bin 
$ xxd -p test.bin 

As I expected this idea is not working, my hypothesis is that I’m getting more then just the binary codes of the function from this process.
I have this idea because the output file test.bin is pretty big 440 bytes that seems to me a little bit too much for literally 7 assembly instructions.

So that’s the reason of my question: How do I get the binary code and only that code?

>Solution :

You accidentally produced an ELF file instead of a simple BIN file. (You can verify this using the file utility if your system has it.)

To produce a small BIN file from your code, change your second command to:

arm-none-eabi-objcopy -j .text test.o -O binary test.bin

Note that there are likely to be tons of complications and security issues when you execute arbitrary machine code received over a serial line. I am not recommending that as a design, just trying to answer the question you asked.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading