Compile a binary file for linking OSX

前端 未结 1 644
后悔当初
后悔当初 2020-12-30 10:55

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 comman

相关标签:
1条回答
  • 2020-12-30 11:46

    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);
    }
    
    0 讨论(0)
提交回复
热议问题