生成最简单的二进制代码obj文件

时间:2014-07-07 12:03:52

标签: gcc assembly compiler-construction linker x86

我需要生成一些包含我的二进制文件的简单obj / o文件 程序体(我需要编写一些非常简单的部分汇编程序)

我需要生成这样的obj二进制文件,我可以使用一些链接器链接并运行我的程序。我想知道 1)什么是最简单的obj格式(我需要的东西,我可以最终与gcc链接,但如果有些思考更容易,据我知道一些工具将一个obj格式转换为另一个,所以我可以使用thic转换器) 2)我想知道这个生成这个obj上下文的代码是什么样的 - 假设我有二进制asm内容要刷新但我只需要制作obj"信封"围绕它

我甚至没有必要刷更多的程序而不是一个(只有一个就足够了,在这种情况下我可以为每个程序生成单独的obj)但我还想要一些代码来嵌入我的导出过程符号名称以及嵌入导入符号的名称(虽然它可能也不那么重要,因为我可以通过参数传递它们...我主要感兴趣的是极端简单性,这将允许我运行这个

假设我说这些数据要冲洗

const int procedure_binary_body_max = 130;

char procedure_binary_body[procedure_binary_body_max]; //130 bytes of procedure body
char* procedure_symbol_name = "sse_dot";

我需要一些代码来制作并将其作为obj文件保存到我可以链接的磁盘上 它与gcc

有人可以帮忙吗?非常tnx

1 个答案:

答案 0 :(得分:0)

注意:以下是针对amd64上的linux,但同样的原则适用于i386。

如果您在调用外部工具时没有问题(在本例中为gcc和nasm),您可以这样做:

main.c中:

#include <stdio.h>
#include <unistd.h>

void make_obj (const char *filename,
               const char *data,
               size_t length,
               const char *entry_point)
{
    const char *filename_s = "tmp.s";
    const char *filename_bin = "tmp.bin";

    FILE *f;
    char buf[1000];

    // create bin file
    f = fopen (filename_bin, "wb");
    fwrite (data, 1, length, f);
    fclose (f);

    // create assembly wrapper
    f = fopen (filename_s, "w");
    fprintf (f,
             "\t\tsection .text\n"
             "\t\tglobal %s\n"
             "%s:\n"
             "\t\tincbin \"%s\"\n",
             entry_point, entry_point, filename_bin);
    fclose (f);

    // call nasm to convert it to object file
    snprintf (buf, 1000, "nasm -f elf64 -o %s %s", filename, filename_s);
    system (buf);

    unlink (filename_bin);
    unlink (filename_s);
}

void test_add (const char *filename_o, const char *entry_point)
{
    const char *filename_c = "test.c";
    const char *filename_exe = "test";

    FILE *f;
    char buf[1000];

    f = fopen (filename_c, "w");
    fprintf (f,
             "#include <stdio.h>\n"
             "\n"
             "extern int %s (int a, int b);\n"
             "\n"
             "int main () {\n"
             "\tconst int a = 2;\n"
             "\tconst int b = 3;\n"
             "\n"
             "\tint c = %s (a, b);\n"
             "\n"
             "\tprintf (\"%%d + %%d = %%d\\n\", a, b, c);\n"
             "\n"
             "\treturn 0;\n"
             "}\n",
             entry_point, entry_point);
    fclose (f);

    snprintf (buf, 1000, "gcc -o %s %s %s",
              filename_exe, filename_c, filename_o);
    system (buf);

    snprintf (buf, 1000, "./%s", filename_exe);
    system (buf);

    unlink (filename_c);
    unlink (filename_exe);
}

int main ()
{
    const char code[] = {
        0x48, 0x89, 0xF8,            // mov rax,rdi
        0x48, 0x01, 0xF0,            // add rax,rsi
        0xC3                         // ret
    };

    const char *filename_o = "tmp.o";
    const char *entry_point = "add";

    make_obj (filename_o, code, sizeof(code), entry_point);
    test_add (filename_o, entry_point);
    unlink (filename_o);

    return 0;
}

用以下方法测试:

cc -o main main.c
./main

如果一切顺利,主要应该生成一个包含整数添加函数的机器代码的目标文件,一个调用机器代码例程的C文件,编译C文件,然后运行它。

结果应该是:

2 + 3 = 5

注释掉unlink()调用以保存中间文件。