2010-08-26 12 views
13

Come esercizio per imparare più precisamente come funzionano i programmi c e quale livello minimo di contenuto deve esistere affinché un programma sia in grado di usare libc, mi sono assunto il compito di programmare principalmente nell'assemblaggio x86 usando gas e ld .Come collegare un programma di assemblaggio gas che utilizza la libreria standard C con ld senza utilizzare gcc?

Come una piccola sfida divertente, ho assemblato e collegato con successo diversi programmi collegati a diverse librerie dinamiche self-made, ma non sono riuscito a codificare un programma da zero per utilizzare le chiamate della funzione libc senza utilizzare direttamente gcc .

Capisco le convenzioni di chiamata delle singole funzioni della libreria c e ho accuratamente controllato i programmi compilati da gcc tramite l'uso di objdump e readelf, ma non ho ottenuto da nessuna parte per quanto riguarda le informazioni da includere in un file assembly gas e quali parametri invocare in ld per collegarsi correttamente a libc. Qualcuno ha qualche idea su questo?

Sto eseguendo Linux su una macchina x86.

risposta

17

Ci sono almeno tre cose che devi fare t o utilizzare correttamente libc con collegamento dinamico:

  1. link /usr/lib/crt1.o, che contiene _start, che sarà il punto di ingresso per i binari ELF;
  2. Link /usr/lib/crti.o (before libc) e /usr/lib/crtn.o (after), che forniscono un codice di inizializzazione e di finalizzazione;
  3. Comunicare al linker che il file binario utilizzerà il linker dinamico, /lib/ld-linux.so.

Ad esempio:

$ cat hello.s 
.text 
.globl main 
main: 
push %ebp 
mov %esp, %ebp 
pushl $hw_str 
call puts 
add $4, %esp 
xor %eax, %eax 
leave 
ret 

.data 
hw_str: 
.asciz "Hello world!" 

$ as -o hello.o hello.s 
$ ld -o hello -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o -lc hello.o /usr/lib/crtn.o 
$ ./hello 
Hello world! 
$ 
+0

questo è estremamente utile, che chiarisce un sacco di informazioni. dopo averlo applicato al mio codice, ricevo 2 errori, "riferimento non definito a '__libc_csu_fini'" e "riferimento non definito a '__libc_csu_init'" dopo aver eseguito un dump di simboli su tutti i file oggetto, non sono riuscito a trovarli simboli e crt1.o sembra chiamare i simboli. c'è qualcosa che potrebbe avere quei simboli all'interno del loro file oggetto? – Cyro

+0

Questi provengono da una parte non condivisa della libreria C; il collegamento con '-lc' dovrebbe inserire'/usr/lib/libc.so', che in realtà è un frammento di script linker che fa riferimento al file corretto ('/ usr/lib/libc_nonshared.a'). Forse un problema con l'ordine dei link? Sono abbastanza sicuro che tu voglia 'crt1.o' seguito da' crti.o' prima, poi i tuoi oggetti e librerie, quindi 'crtn.o' alla fine - ma forse' -lc' dovrebbe venire dopo i tuoi oggetti (poco prima di 'crtn.o'), non prima. –

+0

Sono andato avanti e semplicemente collegato con /usr/lib/libc_nonshared.a subito dopo aver digitato -lc e l'intera cosa ha funzionato! Grazie mille! – Cyro

-1

Penso che qualcosa di simile dovrebbe funzionare:

  1. fare un semplice programma C
  2. gcc -S file.c
  3. modificare file.s
  4. file.s gas
  5. ld file.o -lc crt1.o -o myprog
2

Se si definisce main in assemblea

risposta di Matteo fa un grande lavoro di raccontare i requisiti minimi.

Lascia che ti mostri come trovare questi percorsi nel tuo sistema. Corsa:

gcc -v hello_world.c |& grep 'collect2' | tr ' ' '\n' 

e quindi raccogliere i file menzionati da Matteo.

gcc -v fornisce il comando linker esatto utilizzato da GCC.

collect2 è l'eseguibile interno GCC utilizza come front-end del linker, che ha un'interfaccia simile a ld.

In Ubuntu 14.04 64-bit (GCC 4.8), ho finito con:

ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 \ 
    /usr/lib/x86_64-linux-gnu/crt1.o \ 
    /usr/lib/x86_64-linux-gnu/crti.o \ 
    -lc hello_world.o \ 
    /usr/lib/x86_64-linux-gnu/crtn.o 

Potrebbe anche essere necessario -lgcc e -lgcc_s. Vedi anche: Do I really need libgcc?

Se si definisce _start in assemblea

Se ho definito il _start, il mondo ciao da glibc lavorato con solo:

ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc hello_world.o 

Non sono sicuro se questo è robusto, cioè se le inizializzazioni crt possono essere saltate in sicurezza per richiamare le funzioni di glibc. Vedi anche: Why does an assembly program only work when linked with crt1.o crti.o and crtn.o?

Problemi correlati