2012-04-03 4 views
6

Sto sviluppando per una piattaforma incorporata e sto avendo difficoltà a capire come collegare dinamicamente le librerie condivise. Sto usando il formato di file bFLT e non ho il controllo su dove è caricato il file eseguibile e la libreria condivisa.Codice di posizione indipendente, librerie condivise e faccette di codice - per farle funzionare insieme

Il mio caricatore carica correttamente la libreria condivisa e l'eseguibile in memoria e modifica il GOT dell'eseguibile in fase di esecuzione per collegarsi alla libreria condivisa.

Posso prendere con successo l'indirizzo della funzione e so che è corretto dal disassemblare il codice in quella posizione. Tuttavia, se provo a chiamare la funzione, l'intera cosa si blocca.

Si scopre che GCC aggiunge un "pacchetto di codice" quando chiama le funzioni di libreria condivisa e prende una deviazione quando viene chiamata la funzione e non si dirige effettivamente verso l'indirizzo della funzione. L'indirizzo a cui il codice si ramifica è non riposizionato correttamente perché non viene visualizzato nell'elenco di rilocazioni nel file eseguibile.

Lo smontaggio del rivestimento si presenta così:

000008d0 <__library_call_veneer>: 
8d0: e51ff004 ldr pc, [pc, #-4] ; 8d4 <__library_call_veneer+0x4> 
8d4: 03000320 .word 0x03000320 ; This address isn't correctly relocated! 

Se prendo l'indirizzo della funzione e metterlo in un puntatore a funzione (quindi, bypassando il 'codice di rivestimento') e lo chiamano, il la biblioteca condivisa funziona perfettamente.

Così, per esempio:

#define DIRECT_LIB_CALL(x, args...) do { \ 
     typeof(x) * volatile tmp = x; \ 
     tmp(#args); \ 
    } while (0) 

DIRECT_LIB_CALL(library_call); /* works */ 
library_call(); /* crashes */ 

C'è un modo per entrambi, dire a GCC di non produrre una patina di codice e il ramo direttamente all'indirizzo situato nel GOT o in qualche modo rendere l'indirizzo che i rami impiallacciatura codice apparire nella lista delle delocalizzazioni da eseguire?

+0

State dichiarando i prototipi della libreria usando extern C? –

+0

Sto compilando sotto C così extern "C" sarebbe ridondante, non è vero? – tangrs

+1

Le impiallacciature sono più o meno necessarie sui sistemi ARM, rendendo l'impiallacciatura la cosa giusta da fare. Tuttavia, non aggiornare l'indirizzo non è ... Guardando il tuo formato di file, http://docs.blackfin.uclinux.org/doku.php?id=toolchain:executable_file_formats e http://docs.blackfin.uclinux.org /doku.php?id=toolchain:creating_libraries si presentano. Sembra che tu possa avere un ID di libreria condivisa in conflitto o potresti voler modificare i tuoi flag di collegamento (come spiegato qui). Spiacente non posso aiutare molto di più –

risposta

2

Ho trovato una soluzione a questo problema. Non è il metodo migliore o più pulito, ma fa il lavoro nel mio caso.

Ho sfruttato l'opzione --wrap nel mio linker che reindirizza i simboli a __wrap_symbol. Con questo, ho creato uno script awk che genera automaticamente file ASM che caricano un indirizzo correttamente trasferito nel pc. Qualsiasi chiamata di libreria verrebbe reindirizzata a questo codice. Fondamentalmente quello che ho fatto è stato rendere le mie faccette di codice. Poiché il codice generato non veniva referenziato, veniva semplicemente ottimizzato.

Inoltre, ho dovuto posizionare le faccette nella sezione .data poiché nulla nella sezione .text non è stato riposizionato correttamente. Dato che la piattaforma su cui sto lavorando non distingue molto tra codice e dati, questa soluzione hacky funziona.

Here's a link per il progetto su cui sto lavorando in cui è possibile cercare le specifiche.

+0

Buon lavoro. Vorrei inviare una richiesta di funzionalità agli autori dell'home-home SDK per aggiungere il corretto supporto per il rivestimento ... è una cosa abbastanza basilare per le piattaforme ARM a causa dei limiti di ramificazione ... –