编译用于链接 OSX 的二进制文件

发布于 2024-12-27 19:30:23 字数 692 浏览 1 评论 0原文

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

在linux上使用以下命令: ld -r -b binary -o foo.o foo.bin

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

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 文件

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:无名称列表

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

感谢您的关注

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++.

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

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)

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)

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.

Thanks for looking

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

云仙小弟 2025-01-03 19:30:23

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

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 将存储在段 binaryfoo_bin 部分中> (两个名称都是任意的,但选择模仿 Linux 上 ELF 的 GNU ld)foo.o 对象。

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

要从该部分取回数据,请使用 getsectbyname(结构体在 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 大小归零+1 加上 blob 复制进行字符串化)

警告:自 10.7 起,ASLR 得到更强大,并且与 getsect* 函数严重混淆,导致段错误。在调试条件下运行以重现 EXC_BAD_ACCESS (SIGSEGV) 之前,在 GDB 中将禁用 aslr 设置为关闭。人们必须跳过无序的循环才能找到真正的地址并获得这又工作了。

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

// 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);
}

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

or 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

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

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 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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文