我正在尝试将二进制文件编译成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:没有名单
二进制文件实际上是将下载到外部设备的固件。
感谢您寻找
答案 0 :(得分:9)
这是与Linux链接器命令最接近的转换,用于使用OSX链接器执行二进制嵌入:
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
将存储在binary
对象的段foo_bin
,foo.o
部分(两个名称都是任意的,但选择模仿Linux上的ELF的GNU ld)。
stub
是必要的,因为ld
拒绝仅创建自定义细分/部分。如果您link directly with a real code object,则不需要它。
要从该部分获取数据,请使用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
#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*
功能严重混乱,导致了段错误。 set disable-aslr off
在调试条件下重现EXC_BAD_ACCESS(SIGSEGV)之前的GDB中的run
。人们不得不jump through inordinate hoops找到真正的地址并重新开始工作。
simple workaround是获取偏移和大小,打开二进制文件并直接从磁盘读取数据。这是一个有效的例子:
// 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);
}