Скомпилируйте бинарный файл для компоновки OSX - PullRequest
9 голосов
/ 19 января 2012

Я пытаюсь скомпилировать двоичный файл в объектный файл MACH_O, чтобы его можно было связать в dylib. Дилиб написан на с / с ++.

В Linux используется следующая команда: ld -r -b бинарный -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: список имен отсутствует

На самом деле бинарный файл - это прошивка, которая будет загружена на внешнее устройство.

Спасибо за внимание

1 Ответ

9 голосов
/ 08 декабря 2012

Вот наиболее близкий перевод команды линкера 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);
}
...