目标文件的二进制code [英] Object file to binary code

查看:143
本文介绍了目标文件的二进制code的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们假设我有没有外部的依赖C文件,只有常量数据段。我想编译这个文件,然后得到一个二进制数据,我可以在其他程序中,函数会通过函数指针被用来加载。

Let's suppose I have a C file with no external dependency, and only const data section. I would like to compile this file, and then get a binary blob I can load in another program, where the function would be used through a function pointer.

让我们看一个例子,这里是一个fictionnal二进制模块,在f1.c

Let's take an example, here is a fictionnal binary module, 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,并使用它像这样
在prog.c中

I would like to compile it to f1.o, then f1.bin, and use it like this in prog.c

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?

I suppose going from f1.c to f1.o involves -fPIC to get position independance. What are the flags or linker script that I can use to go from f1.o to f1.bin ?

澄清:

我知道动态链接。动态链接是不可能在这种情况下。连接步骤必须的铸造FUNC指针加载的数据的,如果它是可能的。

I know about dynamic linking. dynamic linking is not possible in this case. The linking step has to be cast func pointer to loaded data, if it is possible.

请假设没有操作系统的支持。如果我可以,我会为例
写在与PC相关的adressing装配F1。

Please assume there is no OS support. If I could, I would for example write f1 in assembly with PC related adressing.

推荐答案

首先,其他说你应该考虑使用DLL左右。

First of all, as other said you should consider using a DLL or SO.

这是说,如果你真的想这样做,你需要更换链接脚本。像这样的东西(不是很好的测试,但我认为它的工作原理):

That said, if you really want to do this, you need to replace the linker script. Something like this (not very well tested, but I think it works):

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

和与提取二进制数据:

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

大概是脚本的一些解释是受欢迎的:

Probably some explanation of the script is welcome:


  • ENTRY(_dummy_start),只是避免了大约没有一个入口点计划的警告。

  • _dummy_start = 0; 定义在previous线使用的符号。该值不被使用。

  • _GLOBAL_OFFSET_TABLE_ = 0; 这prevents另一个链接错误。我不认为你真的需要这个符号,因此它可以被定义为0。

  • 。所有这将收集您的blob的所有字节的节的名称。在此示例中这将是所有的.text 。数据 .RODATA 部分在一起。你可能需要一些更多,如果你在这种情况下复杂的功能, objdump的-x test.o 是你的朋友。

  • LONG(F1 - _all)不是真的需要,但你要知道你的偏移功能进一滴,不是吗?你不能假设它会在0偏移量随着该线路的blob的第一4个字节将符号 F1 (你的函数)来补偿。更改 QUAD 如果使用64位指针。

  • ENTRY(_dummy_start) That just avoids the warning about the program not having an entry point.
  • _dummy_start = 0; That defines the symbol used in the previous line. The value is not used.
  • _GLOBAL_OFFSET_TABLE_ = 0; That prevents another linker error. I don't think you really need this symbol, so it can be defined as 0.
  • .all That's the name of the section that will collect all the bytes of your blob. In this sample it will be all the .text, .data and .rodata sections together. You may need some more if you have complicated functions, in this case objdump -x test.o is your friend.
  • LONG(f1 - _all) Not really needed, but you want to know the offset of your function into the blob, don't you? You cannot assume that it will be at offset 0. With this line the very first 4 bytes in the blob will be the offset of the symbol f1 (your function). Change LONG with QUAD if using 64-bit pointers.

更新:现在一个quick'n'dirty测试(它的工作!):<​​/ p>

UPDATE: And now a quick'n'dirty test (it works!):

#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;

}

这篇关于目标文件的二进制code的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆