如何获得一个C函数的裸骨编译二进制代码?



我正试图在stm32 F4微型上实现嵌入式固件,该固件从串行中获取二进制代码并在微型上执行。

这个想法很简单,当然唯一棘手的部分是,由于在串行上发送原始二进制数据很复杂,我将通过base64编码发送所有内容。

代码如下:

#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] = ''; // 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);
}

下一个问题是能够编译并从这个简单的C函数中获得编译后的二进制代码:

int fn() {
return 3;
}

在这里你可以看到这个愚蠢的函数的程序集。

我尝试了,当然使用用于微主代码的相同工具链,使用位置独立代码的选项用gcc编译它,然后我试图用objcopy复制。text部分,完成我从xxd命令返回的文本,我在base64中对其进行编码,并将其发送到微。

下面是我使用的命令:
$ arm-none-eabi-gcc -fPIC -c test.c
$ arm-none-eabi-objcopy -j .text test.o test.bin 
$ xxd -p test.bin 

正如我所预料的那样,这个想法不起作用,我的假设是,我从这个过程中得到的不仅仅是函数的二进制代码。我有这个想法是因为输出文件test.bin是相当大的440字节,在我看来对于字面上的7个汇编指令有点太多了。

所以这就是我的问题的原因:我如何得到二进制代码,只有那个代码?

您意外地生成了一个ELF文件而不是一个简单的BIN文件。(如果您的系统有file实用程序,您可以使用它来验证这一点。)

要从代码中生成一个小的BIN文件,将第二个命令更改为:
arm-none-eabi-objcopy -j .text test.o -O binary test.bin

请注意,当您执行通过串行线接收的任意机器码时,可能会有大量的复杂性和安全性问题。我不推荐这样的设计,只是想回答你的问题。

最新更新