编译二进制文件以链接OSX [英] Compile a binary file for linking OSX

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

问题描述

我正在尝试将二进制文件编译成MACH_O目标文件,以便可以将其链接到dylib中. dylib是用c/c ++编写的.

I'm trying to compile a binary file into a MACH_O object file so that it can be linked it into a dylib. The dylib is written in c/c++.

在linux上,使用以下命令: ld -r -b二进制-o foo.o foo.bin

On linux the following command is used: ld -r -b binary -o foo.o foo.bin

我曾在OSX上尝试过各种选项,但无济于事:

I have tried various option on OSX but to no avail:

ld -r foo.bin -o foo.o
gives:
ld: warning: -arch not specified
ld: warning: ignoring file foo.bin, file was built for unsupported file format which is not the architecture being linked (x86_64)

已创建一个空的.o文件

An empty .o file is created

ld -arch x86_64 -r foo.bin -o foo.o 
ld: warning: ignoring file foo.bin, file was built for unsupported file format which is not the architecture being linked (x86_64)

再次创建一个空的.o文件.用nm检查文件会得到: nm foo.o nm:没有名单

Again and empty .o file is created. Checking the files with nm gives: nm foo.o nm: no name list

二进制文件实际上是将下载到外部设备的固件.

The binary file is actually, firmware that will be downloaded to an external device.

感谢您的关注

推荐答案

以下是与Linux链接器命令最接近的翻译,以使用OSX链接器执行二进制嵌入:

Here's the closest translation to the Linux linker command to perform binary embedding with the OSX linker:

touch stub.c
gcc -o stub.o -c stub.c
ld -r -o foo.o -sectcreate binary foo_bin foo.bin stub.o

foo.bin将存储在foo.o对象的段binary的段foo_bin中(两个名称都是任意的,但被选择为模仿Linux上用于ELF的GNU ld).

foo.bin will be stored in segment binary, section foo_bin (both names are arbitrary but chosen to mimic GNU ld for ELF on Linux) of the foo.o object.

stub是必需的,因为ld拒绝仅创建自定义的段/节.如果您直接与真实代码链接,则不需要对象.

stub is necessary because ld refuses to create just a custom segment/section. You don't need it if you link directly with a real code object.

要从该部分获取数据,请使用

To get data back from the section, use getsectbyname (struct is defined in mach-o/loader.h):

#include <mach-o/getsect.h>
const struct section_64 *sect = getsectbyname("binary", "foo_bin");
char *buffer = calloc(1, sect->size+1);
memcpy(buffer, sect->addr, sect->size); // whatever

getsectdata :

#include <mach-o/getsect.h>
size_t size;
char *data = getsectdata("binary", "foo_bin", &size);
char *buffer = calloc(1, size+1);
memcpy(buffer, data, size); // whatever

(我用它来存储文本数据,因此通过calloc将size + 1归零并加上斑点复制来进行字符串化处理)

(I used it to store text data, hence the stringification via calloc zeroing of size+1 plus blob copying)

警告:自10.7起,ASLR变得更强大,并严重破坏了getsect*函数,从而导致了段错误.在调试条件下,在run之前在GDB中的set disable-aslr off可以重现EXC_BAD_ACCESS(SIGSEGV).人们必须跳过无谓的箍才能找到真实地址并获得再次起作用.

Warning: Since 10.7, ASLR got stronger and messes badly with getsect* functions, resulting in segfaults. set disable-aslr off in GDB before running to reproduce EXC_BAD_ACCESS (SIGSEGV) in debug conditions. People had to jump through inordinate hoops to find the real address and get this working again.

A 简单的解决方法是获取偏移量和大小,打开二进制文件并直接从磁盘读取数据.这是一个工作示例:

A simple workaround is to get the offset and size, open the binary and read the data straight from disk. Here is a working example:

// main.c, build with gcc -o main main.c foo.o
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <mach-o/getsect.h>

int main() {
    // finding the filename of the running binary is left as an exercise to the reader
    char *filename = "main";

    const struct section_64 *sect = getsectbyname("binary", "foo_bin");
    if (sect == NULL) {
        exit(1);
    }

    char *buffer = calloc(1, sect->size+1);
    int fd = open(filename, O_RDONLY);
    if (fd < 0) {
        exit(1);
    }
    lseek(fd, sect->offset, SEEK_SET);
    if (read(fd, buffer, sect->size) != sect->size) {
        close(fd);
        exit(1);
    }

    printf("%s", buffer);
}

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

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