Вот наиболее близкий перевод команды линкера 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
(оба имени произвольны, но выбраны для имитации GNU ld для ELF в Linux) объекта 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 плюс копирование больших двоичных объектов)
Предупреждение : Начиная с 10.7, ASLR стал сильнее и плохо работает с getsect*
функциями, что приводит к ошибкам сегмента. set disable-aslr off
в GDB до run
ning для воспроизведения EXC_BAD_ACCESS (SIGSEGV) в условиях отладки. Люди должны были перепрыгнуть через непоследовательные обручи , чтобы найти реальный адрес и снова заработать.
A Простой обходной путь - получить смещение и размер, открыть двоичный файл и прочитать данные прямо с диска. Вот рабочий пример:
// 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);
}