2013-08-15 8 views
59

Quello che faccioAlias ​​di simboli deboli su OS X simili a quelli su Linux o equivalenti più simili?

Durante la scrittura di librerie condivise per Linux, tendo a prestare attenzione alle delocalizzazioni, la visibilità simbolo, GOT/PLT ecc

Se del caso, sto cercando di evitare di chiamare stub PLT quando le funzioni della stessa libreria si chiamano a vicenda. Ad esempio, supponiamo che un oggetto condiviso fornisca due funzioni pubbliche: foo() e bar() (entrambi possono essere richiamati dall'utente). La funzione bar(), tuttavia, chiama anche foo(). Quindi quello che faccio in questo caso è questo:

  1. Definire _foo() e _bar() funzioni che hanno la visibilità privato.
  2. Definire foo() e bar() alias deboli rispettivamente per _foo() e _bar().

In questo modo, il codice nell'oggetto condiviso non utilizza mai simboli deboli. Richiama solo le funzioni locali, direttamente. Ad esempio, quando viene richiamato _bar(), chiama direttamente _foo().

Ma gli utenti non sono a conoscenza delle funzioni _* e utilizzano sempre gli alias deboli corrispondenti.

Come faccio

In Linux, questo si ottiene con il seguente comando:

extern __typeof (_NAME) NAME __attribute__(weak, alias("_NAME")); 

Il problema

Purtroppo, questo non funziona per OS X Non ho alcuna conoscenza approfondita di OS X o dei suoi formati binari, quindi ho cercato un po 'e ho trovato alcuni esempi di funzioni deboli (come this one), ma quelli non q fai lo stesso come puoi avere un simbolo debole, ma non un simbolo debole che è un alias per la funzione locale del DSO.

Possibile soluzione ...

Per ora, ho solo disabilitato questa funzione (che viene implementata utilizzando le macro), in modo che tutti i simboli sono globali e avere una visibilità di default. L'unico modo in cui posso pensare di ottenere lo stesso risultato ora è avere tutte le funzioni _foo con visibilità privata e avere le corrispondenti funzioni foo con visibilità predefinita e chiamare le loro controparti "nascoste".

Un modo migliore?

Ciò, tuttavia, richiede una buona parte del codice da modificare. Quindi preferirei non andare lì a meno che non ci sia davvero nessun altro modo.

Quindi qual è l'alternativa di OS X o il modo più semplice per ottenere la stessa semantica/comportamento?

+2

è il vostro obiettivo è semplicemente quello di evitare il sovraccarico di chiamate via stub PLT quando si effettua una chiamata a un simbolo all'interno della stessa biblioteca? Hai confermato che il linker non si sta già occupando di questo per te? – bdash

+0

@bdash: Sì, ma non solo. L'altro obiettivo è fare in modo che il compilatore esegua più ottimizzazioni: i simboli privati ​​sono ottimizzati meglio, incluso LTO. E linker non esegue questa ottimizzazione, perché non può garantire che LD_PRELOAD non verrà utilizzato. In altre parole, una volta che si passa al collegamento dinamico, si va fino in fondo. –

+8

La mia comprensione è che quello che stai cercando è il comportamento predefinito per le librerie condivise su OS X. L'unica parte della documentazione che ho trovato che si avvicina a renderla esplicita è la sezione della pagina man di 'ld' riguardo a' -interposable_list argomento. Afferma che le chiamate ai simboli all'interno di un modulo saranno chiamate dirette a meno che quel simbolo non sia contrassegnato come interposto, nel qual caso verrà effettuato tramite uno stub dyld. – bdash

risposta

1

Su OS X, le chiamate effettuate all'interno della libreria sono chiamate dirette automaticamente e non passano attraverso lo stub dyld.La prova del fatto è che se si desidera essere in grado di iniettare funzioni alternative per servire una chiamata, è necessario utilizzare l'interposizione per forzare l'accesso indiretto ai simboli e forzare l'esecuzione della chiamata attraverso gli stub dyld. Altrimenti, per impostazione predefinita, le chiamate locali saranno dirette e non dovranno sostenere il sovraccarico di esecuzione di dyld.

Pertanto, l'ottimizzazione su Linux è già il comportamento predefinito e l'alias non è necessario.

Tuttavia, se si desidera effettuare questa operazione solo per semplificare il codice compatibile con la piattaforma, è comunque possibile effettuare gli alias. Hai solo bisogno di usare "weak_import" o "weak" (se vuoi coalesced) come nome attributo.

extern typeof (_NAME) NOME __attribute (weak_import, alias ("_ NAME"));

riferimento Apple sul collegamento debole: Marking Symbols for Weak Linking
riferimento Apple su Mach-O runtime vincolante: Scope and Treatment of Symbol Definitions