Ruolo del collegamento, dei file oggetto e dei file eseguibili

4
  1. Per un programma C o assembly che non richiede altre librerie, eseguirà il collegamento essere necessario? In altre parole, la conversione da C a Assembly e / o da Assembly a un file oggetto sarà sufficiente senza essere seguita dal collegamento?

    Se il collegamento è ancora necessario, cosa lo farà, dato che c'è solo un file oggetto che non lo fa bisogno di una libreria per il collegamento a?

  2. In relazione a quanto diversi sono i file oggetto e i file eseguibili, dato che in Linux entrambi hanno il formato file ELF?

    I file oggetto sono quei file ELF che non sono eseguibili?

    Esistono alcuni file eseguibili che possono essere collegati ai file oggetto? Se sì, significa collegamento dinamico di file eseguibili a condivisi biblioteche?

posta Tim 01.08.2011 - 05:02
fonte

3 risposte

8

Prima di tutto, è davvero difficile per qualsiasi programma non banale 'non richiedere altre librerie'. Ricorda che glibc e il codice di avvio che chiama main() sono anche librerie.

Ma sì, anche in questo caso è necessario il linker, solo perché il compilatore / assemblatore di solito non gestisce il formato ELF (o qualsiasi formato eseguibile). Proprio perché di solito devi collegarti con alcune librerie, quindi perché dovrebbe preoccuparsi di compilare in ELF? È meglio concentrarsi su formati di codice collegabili e lasciare i formati eseguibili al linker.

PS: ho dimenticato che .so è anche una variante di ELF. Ma non cambia il fatto che si tratta di un sottoformato diverso ei dettagli dell'eseguibile non sono inclusi nella maggior parte dei compilatori / assembers.

Sì, è possibile che un singolo strumento si compili direttamente su eseguibile, ma ciò significa semplicemente che include sia il compilatore che il linker in un singolo comando. Perché considererebbe il caso (molto) speciale quando non aggiungerai altro codice? È molto più logico farlo nel linker, dopotutto ne avrai bisogno in% 99.9 casi.

    
risposta data 01.08.2011 - 06:16
fonte
1

Dipende dal sistema operativo. In generale, però, è necessario qualcosa per convertire il file oggetto in un file eseguibile. I file oggetto sono generalmente progettati per essere l'input nel linker e non per essere eseguiti direttamente.

Ci sono pochissimi, se ce ne sono, programmi utili che non hanno bisogno di avere librerie collegate con loro. (Forse statico, forse dinamico, ma senza l'infrastruttura della libreria, non avrai molto lavoro utile.)

    
risposta data 02.08.2011 - 07:28
fonte
1

Il tuo programma avrà (come minimo) bisogno di collegarsi a un caricatore per l'esecuzione. Considera il seguente codice banale:

tpost@tpost-desktop:~$ cat count.c
int main(void)
{
        unsigned int i;

        for (i = 0; i < 10; i++) {;;}

        return 0;
}

Ora lo compiliamo:

tpost@tpost-desktop:~$ gcc -Wall -o count count.c

E ora esaminiamo cosa ha fatto il linker:

    linux-gate.so.1 =>  (0x002b5000)
    libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x00482000)
    /lib/ld-linux.so.2 (0x00241000)

    Version information:
    ./count:
            libc.so.6 (GLIBC_2.0) => /lib/tls/i686/cmov/libc.so.6
    /lib/tls/i686/cmov/libc.so.6:
            ld-linux.so.2 (GLIBC_PRIVATE) => /lib/ld-linux.so.2
            ld-linux.so.2 (GLIBC_2.3) => /lib/ld-linux.so.2
            ld-linux.so.2 (GLIBC_2.1) => /lib/ld-linux.so.2

Di interesse è il fatto che ldd non ha trovato file fisico per linux-gate.so.1 e ld-linux.so.2 , questo perché entrambi sono virtual oggetti dinamici condivisi che risiedono in ogni spazio di indirizzamento del processo . Gli oggetti condivisi sono esposti dal kernel e contengono il codice necessario per caricare effettivamente il programma, che funziona in congiunzione con la libreria C del sistema.

Colleghiamo staticamente questo, vogliamo?

tpost@tpost-desktop:~$ gcc -static -Wall -o count count.c
tpost@tpost-desktop:~$ ldd -v count
        not a dynamic executable

Non ho eliminato la dipendenza di collegamento qui, tutto ciò che ho fatto è stato preso il codice del loader e la libreria del sistema C e li ho resi parte dell'eseguibile. Sembra un po 'sciocco, perché il mio eseguibile non usa più una copia perfettamente valida di quel codice che è già in memoria.

Potresti scrivere il tuo codice loader e non usare quello fornito dalla libreria C di sistema, ma non perderete le dipendenze dal caricatore del kernel stesso.

Questo è un esempio molto orientato a Linux, ma è tutto ciò che ho a disposizione per illustrare il punto:)

    
risposta data 02.08.2011 - 08:30
fonte

Leggi altre domande sui tag