gpt4 book ai didi

c - 目标文件到二进制代码

转载 作者:太空狗 更新时间:2023-10-29 17:00:42 24 4
gpt4 key购买 nike

假设我有一个没有外部依赖的 C 文件,只有 const 数据部分。我想编译这个文件,然后得到一个二进制 blob,我可以加载到另一个程序中,其中函数将通过函数指针使用。

举个例子,这是一个虚构的二进制模块,f1.c

static const unsigned char mylut[256] = {
[0 ... 127] = 0,
[128 ... 255] = 1,
};

void f1(unsigned char * src, unsigned char * dst, int len)
{
while(len) {
*dst++ = mylut[*src++];
len--;
}
}

我想把它编译成f1.o,然后是f1.bin,然后像这样使用在程序中

int somefunc() {
unsigned char * codedata;
f1_type_ptr f1_ptr;
/* open f1.bin, and read it into codedata */

/* set function pointer to beginning of loaded data */
f1_ptr =(f1_type_ptr)codedata;

/* call !*/
f1_ptr(src, dst, len);
}

我想从 f1.c 到 f1.o 涉及 -fPIC 以获得位置独立性。我可以使用哪些标志或链接描述文件从 f1.o 到 f1.bin ?

澄清:

我知道动态链接。在这种情况下动态链接是不可能的。如果可能的话,链接步骤必须是将函数指针转换为加载的数据

请假设没有操作系统支持。如果可以的话,我会举个例子用 PC 相关的寻址在汇编中写入 f1。

最佳答案

首先,正如其他人所说,您应该考虑使用 DLL 或 SO。

也就是说,如果你真的想这样做,你需要替换链接描述文件。像这样的东西(没有经过很好的测试,但我认为它有效):

ENTRY(_dummy_start)
SECTIONS
{
_dummy_start = 0;
_GLOBAL_OFFSET_TABLE_ = 0;
.all : {
_all = .;
LONG(f1 - _all);
*( .text .text.* .data .data.* .rodata .rodata.* )
}
}

然后编译:

$ gcc -c -fPIC test.c

链接:

$ ld -T script.ld test.o -o test.elf

然后使用以下命令提取二进制 blob:

$ objcopy -j .all -O binary test.elf test.bin

可能欢迎对脚本进行一些解释:

  • ENTRY(_dummy_start) 这只是避免了有关程序没有入口点的警告。
  • _dummy_start = 0; 定义了上一行中使用的符号。该值未使用。
  • _GLOBAL_OFFSET_TABLE_ = 0; 这可以防止另一个链接器错误。我不认为你真的需要这个符号,所以它可以定义为 0。
  • .all 这是将收集 blob 的所有字节的部分的名称。在此示例中,它将所有 .text.data.rodata 部分放在一起。如果你有复杂的功能,你可能需要更多,在这种情况下 objdump -x test.o 是你的 friend 。
  • LONG(f1 - _all) 不是真的需要,但您想知道函数在 blob 中的偏移量,不是吗?您不能假设它将位于偏移量 0。对于这一行,blob 中的前 4 个字节将是符号 f1(您的函数)的偏移量。如果使用 64 位指针,请将 LONG 更改为 QUAD

更新:现在是一个快速的'n'dirty 测试(它有效!):

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>

typedef void (*f1_t)(char *a, char *b, int len);
f1_t f1;

int main()
{
char *blob = (char*)valloc(4096);
FILE *f = fopen("test.bin", "rb");
fread(blob, 1, 4096, f);
fclose(f);

unsigned offs = *(unsigned*)blob;
f1 = (f1_t)(blob + offs);
mprotect(blob, 4096, PROT_READ | PROT_WRITE | PROT_EXEC);
char txt[] = "¡hello world!";
char txt2[sizeof(txt)] = "";
f1(txt, txt2, sizeof(txt) - 1);
printf("%s\n%s\n", txt, txt2);
return 0;

}

关于c - 目标文件到二进制代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12138433/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com