Il Processo di Linking in Linux

Per realizzare un programma o qualsiasi altro componente software dobbiamo scrivere il codice in un linguaggio di programmazione e poi sottoporlo al compilatore che produce dei file oggetto e che poi verranno uniti, insieme ad altri componenti, nella fase di link ( collegamento ). In questo articolo vedremo come funziona questo processo nei sistemi Unix-like, come Linux e più in particolare in tutti quei sistemi in cui sono disponibili compilatori e tool forniti con GNU Collection Compiler ( gcc ) e dove il formato dei file oggetto è l’ELF ( Executable and Linkable Format ). Un file ELF è formato dai seguenti elementi:

  • Header ELF – parte del file oggetto contenente informazioni relative all’identificativo del file ( magic number ) ed i puntatori ( offset ) per raggiungere il Program Header Table e la Section Header Table.
  • Program Header Table – sezione contenente informazioni adoperate a run-time come ad esempio il mapping dei file su un processo o la posizione della prima routine ( entry point ) a cui passare il controllo dopo la fase di loading ( caricamento ) in memoria del file.
  • Sezioni – sono addette a contenere istruzioni del programma, i dati, la tabella dei simboli, informazioni per il debug ed altro. Il nome delle sezioni in genere viene preceduto da un punto, come .start per l’inizio del programma.
  • Section Header Table – contiene i dati relativi ad una sezione come, ad esempio, la sua grandezza, il tipo, l’offset dei file per poterla prelevare ed altro.

Ogni file ELF deve contenere almeno l’Header, che deve essere collocato necessariamente all’inizio del file oggetto. Per i file eseguibili deve essere inoltre presente anche la Program Header Table che contiene tutte le specifiche del sistema operativo. Veniamo a un esempio pratico molto semplice, ma che ci consente di vedere come funziona la creazione di un eseguibile. Dapprima scriviamo il codice sorgente nel file main.c in linguaggio C:

#include "stdio.h"

void main()
{
   int a, b, tot;

   a = 5;
   b = 7;

   tot = a + b;

   printf("La somma di %d e %d risulta di %d\n", a, b, tot);
}

Abbiamo scritto un programma elementare e veniamo a creare il file oggetto con questo comando:

gcc -c main.c

Con l’opzione -c chiediamo al compilatore di creare il file in codice assembly, a questo punto nella stessa directory abbiamo il file oggetto main.o.  Con il comando nm possiamo vedere le funzioni contenute nel file oggetto ed anche quelle non definite nello stesso file, nel nostro caso l’output del comando:

nm –undefined-only main.o

sarà U printf, che infatti è una funzione che risiede nelle librerie standard e che possiamo utilizzare perché abbiamo inserito #include “stdio.h” all’inizio del file sorgente. A questo punto passiamo alla fase di collegamento ( linking ) richiamando questo comando:

gcc -o somma main.o

L’opzione -o significa appunto collegare i vari file oggetto. Una volta creato il file eseguibile somma possiamo lanciarlo con il comando:

./somma

l’output del programma sarà “La somma di 5 e 7 risulta di 12”.

Per qualsiasi dubbio o informazione vi invito ad iscrivervi al nostro forum su Linux.

Continua con l’articolo: link dinamico e statico su Linux.

Di Giampaolo Rossi

Sviluppatore software da oltre 16 anni.