2012-11-02 10 views
26

Non posso essere l'unico a trovarlo.Come posso collegare (o aggirare) due librerie statiche di terze parti che definiscono gli stessi simboli?

Ho un'applicazione C++ che deve collegarsi con una libreria di terze parti e un'altra libreria statica in un SDK. L'SDK ha ricompensato, per qualche ragione orribilmente frustrante, un sottoinsieme della stessa libreria di terze parti nella propria libreria (rinominata), sebbene i simboli stessi siano denominati uguali e non siano incapsulati all'interno di uno spazio dei nomi. La mia stessa applicazione dipende dalla stessa libreria di terze parti.

Ho preso in considerazione alcune opzioni, ma forse mi manca qualcosa e spero che un nuovo look mi possa aiutare. Forse sono vicino e qualcuno saprà il prossimo passo per uno di questi. Elencherò ciò che ho provato e le carenze di ciascuna soluzione fino ad ora:

  1. Collegamento con entrambi. Ottengo circa 2500 righe di avvertimenti e errori di modifica della dimensione/modifica del simbolo. Questo è quando ho scoperto che hanno definito gli stessi simboli. Sto cercando di ricompilare OpenSSL con g ++ e rilasciarlo in un namespace al momento ... vedi modifica sotto ...

  2. Collegamento solo con l'SDK. Ricevo simboli indefiniti da cui dipende il mio codice - questo è quando ho scoperto che la loro ricompilazione della lib di terze parti è un sottoinsieme, o almeno è stata configurata con un modulo disabilitato.

  3. Collegamento solo con la terza parte di lib. Ho un paio di simboli indefiniti segnalati dall'SDK - uno di questi è in realtà un #define in un file di intestazione all'interno della lib di terze parti, quindi tutti i riferimenti nella lib di terze parti si risolvono nella definizione, ma i riferimenti all'esterno non lo fanno . L'ho spostato nel file c, che risolve il problema, tuttavia ho ancora due funzioni irrisolte che non riesco a trovare da nessuna parte. Questo è il più vicino che ho ottenuto finora.

  4. Separa simboli in conflitto da una libreria e un collegamento in entrambi. Finora questo non ha funzionato. Potrebbe trattarsi di un problema di versione tra la lib statically linked in SDK e le versioni che ho provato a utilizzare della lib di terze parti, ma sembra che alcune funzioni siano state spostate tra i simboli, quindi rimuovendo un simbolo, rimuovo inavvertitamente un funzione di cui ho bisogno altrove. Non sembra esserci una mappatura perfetta tra le funzioni nei simboli nell'SDK e le funzioni nei simboli nella lib di terze parti. È plausibile rimuovere le funzioni senza dover regolare manualmente gli indirizzi?

Sto esaminando i simboli in librerie con:

nm -C --defined-only lib<name>.a 

ed estrarre interi oggetti con:

ar -x lib<name>.a <objname>.o 

Speriamo che questo aiuterà anche altri che hanno avuto a collegare con il terzo - librerie di terze parti in conflitto tra loro. Per motivi di specifiche, la lib di terze parti è OpenSSL e l'SDK è Opsec - libcpopenssl.a è la libreria di offensiva in Opsec.

** MODIFICA- Una soluzione ritardata per l'immissione di dati può essere quella di ricompilare OpenSSL con g ++ e inserire l'intera cosa in uno spazio dei nomi, quindi collegare entrambe le librerie. Lo sto provando ora ... altro a venire ...

+0

Puoi lasciare * fuori * la derivata opsec openssl e collegare invece OpenSSL? Sembra che abbiano incluso libcopopenssl.a nel caso in cui non avessi OpenSSL con cui collegarti. I simboli dovrebbero essere collegati se dividono correttamente la loro derivata OpenSSL. Cioè collega tutto il resto nel loro lib-set * eccetto * che lib, e collega invece OpenSSL. – WhozCraig

+0

Ecco cosa ho provato al punto # 3 sopra, in sostanza. Ho dovuto spostare un #define in un file C e ricompilare, e quindi avevo ancora due simboli non definiti. Non riesco a trovare SSL_get_peer_dh o DH_dup ovunque. – rutgersmike

+0

Non potresti scrivere con 'nm' per afferrare i simboli dal * buon * OpenSSL. Quindi elimina la * cattiva * lib di questo elenco di nomi. Se sono collegati in modo statico, i riferimenti interni sono già risolti. In caso contrario, utilizzare '-r' o' -Ur' sul linker. –

risposta

3

Una ricerca di Google indica che SSL_get_peer_dh e DH_dup sono in realtà aggiunte da libcpopenssl.a e che non esistono nemmeno nella mia copia di OpenSSL.Quindi dovrai davvero collegare la libreria. Combinare entrambe le librerie (approccio 4 sopra) a livello binario è improbabile che funzioni - OpenSSL è molto schizzinoso riguardo al suo ABI (di solito hanno i file .so versione ridotta al numero minore) quindi dovresti essere molto fortunato ad avere un .so che sia compatibile con ABI per il loro file .a.

Il mio suggerimento è una variante dell'Approccio 4, ma a livello di sorgente: avrete il collegamento in Opsec libcpopenssl.a, poiché è una versione modificata di OpenSSL che include simboli extra (e possibilmente altre modifiche) e cattura le funzioni extra necessarie dai sorgenti OpenSSL e ricompilare quegli oggetti con libcpopenssl.a, in modo che possano usare le funzioni dalla versione Opsec. Se stai usando solo alcune funzioni di OpenSSL che non vengono esportate da libcpopenssl.a, questo è abbastanza fattibile.

Concesso, questo è ancora un approccio ingombrante, ma è un modo garantito per ottenere la compatibilità dei simboli, a condizione ovviamente che l'SDK Opsec non abbia apportato modifiche semantiche a OpenSSL che interromperà le funzioni OpenSSL aggiuntive a cui si sta lavorando il tuo progetto.

(Sono nuovo su StackOverflow, quindi non so se questo suggerimento è la risposta giusta, ma non ho punti reputazione per postare commenti, lo rimuoverò se è inappropriato.)

+0

Non sono riuscito a trovare molto su quelle funzioni, grazie! Mi sono stancato di modificare OpenSSL, ma è un po 'dove sono diretto, cercherò di compilarlo per C++ e di farlo cadere in uno spazio dei nomi. Aggiornerò quando avrò più informazioni. – rutgersmike

1

Se siete morbosamente curiosi, 249 file sono stati modificati nella versione più recente di OpenSSL per farlo compilare. Il problema più comune è stato l'abbondanza di cast di puntatori in stile C, in particolare con void *. Ora vedo "reinterpret_cast" nei miei sogni.

Questo non ha risolto il problema da solo, ma deve ancora essere inserito in uno spazio dei nomi nella sua interezza, il che significa modificare di nuovo tutti i file oltre ai miei riferimenti interni. Penso che lo passerò per ora.

Grazie per l'aiuto di tutti.

Problemi correlati