2012-01-19 16 views
6

Estoy intentando compilar un archivo binario en un archivo de objeto MACH_O para que pueda vincularlo a un archivo dylib. El dylib está escrito en c/C++.Compilar un archivo binario para vincular OSX

En Linux se utiliza el siguiente comando: ld -r -b binaria -o foo.o foo.bin

He intentado varias opciones en OSX, pero en vano:

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) 

un archivo .o vacío se crea

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) 

una vez más y se crea el archivo .o vacía. Comprobación de los archivos con nm da: nm foo.o nm: no hay lista de nombres

El archivo binario es, en realidad, el firmware que será descargado a un dispositivo externo.

Gracias por mirar

+0

solo deberías hacer algo como 'ld -dylib -o libFoo.dylib fooSource * .o'. el problema parece ser con foo.bin - si haces 'file foo.bin' ¿qué dice? –

+0

La salida del archivo foo.bin es: 'foo.bit: Xilinx datos BIT - de foo.ncd; HW_TIMEOUT = FALSE; nosotros - para 0xFFFFFFFF - construido slx16ftg256 (011/03/15) - longitud de datos 0x31373a35' – Satpal

+0

hmm Me temo que no parece que LLVM clang ld haga la inserción de blobs binarios que hace el gnu ld.es posible que desee intentar instalar gcc desde macports (http://www.macports.org/)? no estoy seguro si eso ayudaría, pero podría valer la pena intentarlo. –

Respuesta

7

Aquí está la traducción más cercana al comando de enlace de Linux para realizar la incrustación binario con el enlazador 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 se almacenarán en el segmento binary, sección foo_bin (ambos nombres son arbitrario pero elegido para imitar GNU ld para ELF en Linux) del objeto foo.o.

stub es necesario porque ld se niega a crear solo un segmento/sección personalizado. No lo necesita si link directly with a real code object.

para obtener datos de vuelta de la sección, utilice getsectbyname (struct se define en 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 

o 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 utilizado para almacenar datos de texto, de ahí el stringification vía calloc puesta a cero del tamaño + 1 más copia de blob)

Warning: Desde 10.7, ASLR se volvió más fuerte y se equivoca con las funciones getsect*, lo que da como resultado segfaults. set disable-aslr off en GDB antes de run para reproducir EXC_BAD_ACCESS (SIGSEGV) en condiciones de depuración. La gente tenía que llamar al jump through inordinate hoops para encontrar la dirección real y hacer que esto funcione de nuevo.

A simple workaround es obtener el desplazamiento y el tamaño, abrir el binario y leer los datos directamente desde el disco. Este es un ejemplo de trabajo:

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

Parece que hay versiones 'getsection *' ligeramente más nuevas de las funciones 'getsect *' que se pueden usar y que no se ven afectadas por los problemas de ASLR. Un poco más agradable que tener que leer el binario en bruto. –

+0

http://gareus.org/wiki/embedding_resources_in_executables también señala que el nombre de sección pasado a '-sectcreate' no puede ser más largo que ** 16 ** caracteres ... – cfstras

Cuestiones relacionadas