Hallo,
Folgendes Problem:
Ein VST-Plugin-Host wurde mit JUCE version A gebaut. Ein VST-Plugin wurde mid JUCE version B gebaut.
Der VST-Plugin-Host verwendet ein shared object mit JUCE-Symbolen. Das VST-Plugin ist ein shared object mit JUCE-Symbolen.
Wie kann ich herausfinden, ob der Host ausschließlich gegen seine eigenen JUCE-Symbole gelinkt wird und ob das Plugin ausschließlich gegen seine version gelinkt wird.
Wenn das VST-SDK das unterstützt könnte ich gcc anweisen, das Plugin mit visibility=hidden zu compilieren.
Beim Host ist mir das nicht so klar.
Außerdem möchte ich gern anhand der shared objects sehen, welche Symbole exportiert werden. Das geht doch irgendwie mit objdump oder nm. Hat das schonmal jemand gemacht? Wie geht das genau?
Viele Grüße Tobias
Hi,
vorweg: ich habe keine Ahnung was JUCE ist und welche Link-Anforderungen es hat.
Fast immer sollte man so eine Situation vermeiden. Du hast keinerlei Garantie dass es funktioniert.
Der Runtime-Linker macht ein paar Annahmen zu dem Zeug das er in den Speicher lädt:
* Jede Bibliothek kommt nur einmal vor, der selbe Name kann auf die selbe Datei abgebildet werden * Niemand kommt auf die tollkühne Idee absichtlich zwei Versionen der selben Bibliothek zu linken * Unterschiedliche Module, die gelinkt werden, haben auch unterschiedliche Symbole - wenn ich ein Symbol gefunden habe, brauche ich nicht weiter zu suchen. * Weak-Symbole zeigen auf identische Funktionalität und es ist egal welche Instanz ich wohin verlinke.
Es gibt noch ein paar mehr Annahmen, aber in jedem Fall ist eine Verletzung der Annahmen keine gute Idee und führt zu viel Ärger und Kopfschmerz.
On 12/02/2022 18:14, Tobias Schlemmer wrote:
Ein VST-Plugin-Host wurde mit JUCE version A gebaut. Ein VST-Plugin wurde mid JUCE version B gebaut.
Der VST-Plugin-Host verwendet ein shared object mit JUCE-Symbolen. Das VST-Plugin ist ein shared object mit JUCE-Symbolen.
Wie kann ich herausfinden, ob der Host ausschließlich gegen seine eigenen JUCE-Symbole gelinkt wird und ob das Plugin ausschließlich gegen seine version gelinkt wird.
Host: Du müsstest den Host zwingen seine Symbole gleich beim Laden aufzulösen und nach Möglichkeit die Symbole im Plugin verstecken (visibility=hidden).
Plugin: du hast keine Garantie. Selbst wenn Du statisch linkst, mit private linkage und visibility=hidden. Selbst interne Symbole werden erst zur Laufzeit aufgelöst, weil der Linker vorher nicht weiß an welcher Adresse eine Funktion landen wird. Symbole im Host zu verstecken ist vermutlich keine gute Idee, wenn andere Plugins noch funktionieren sollen. Selbst wenn das gehen sollte ist es keine Garantie dass die versteckten Symbole wirklich auch nur lokal verlinkt werden.
Wenn das VST-SDK das unterstützt könnte ich gcc anweisen, das Plugin mit visibility=hidden zu compilieren.
Beim Host ist mir das nicht so klar.
Außerdem möchte ich gern anhand der shared objects sehen, welche Symbole exportiert werden. Das geht doch irgendwie mit objdump oder nm. Hat das schonmal jemand gemacht? Wie geht das genau?
ldd zeigt Dir welche Bibliotheken gefunden werden und wo sie hingelegt werden.
nm zeigt Dir welche Symbole exportiert und importiert werden, aber nicht wo sie hergeholt werden.
objdump kann Dir relativ low-level alles anzeigen was an Export, Import, Symboltabellen, Relocations etc. in einer Datei drin ist. Aber Du musst selbst wissen was der Runtime-Linker damit anstellt.
Setze die Variable LD_DEBUG=all und starte Dein Programm - auf stderr bekommst Du eine Liste aller Symbolauflösungen so wie sie live passieren.
Du wirst sehen dass Du eine Menge Möglichkeiten hast, aber bis Du diese Möglichkeiten gelernt hast und rausgefunden hast wie Du den Linker dazu bewegst Symbole umzubiegen, zu verstecken, hart zu binden, etc.pp. bist Du wahrscheinlich wesentlich schneller und effektiver fertig wenn Du einfach alles auf eine einheitliche Version von JUCE portierst und identisch linkst.
Je nachdem was JUCE macht kann es auch unmöglich sein es stabil zu machen: Qt zum Beispiel dreht komplett frei wenn man zwei Versionen der Core-Bibliothek in den Speicher lädt.
Konrad
Hallo Konrad,
vielen Dank für die Erklärungen. LD_DEBUG könnte ich mir mal angucken.
Das Problem besteht darin, dass Du bei VST keine Kontrolle über die Plugin-Bibliotheken hast. Da geht es darum, dass Leute ihre proprietären Plugins verkaufen, die in eine nicht näher zu benennende Software von Steinberg eingeklinkt werden sollen. Die Schnittstelle wird vom SDK bereitgestellt und darübr hinaus darf man keine Annahmen was sonst noch verfügbar sein sollte (d.h. keine GUI usw). Das geht auch mit Windows-DLLs ganz gut, unter *nix muss man wohl die libdl komplett ersetzten.
Inzwischen ist man soweit, dass man auch GPL3-Plugins und GPL3-Hosts zulässt.
Was JUCE angeht: Das ist ein Plattformübergreifendes GUI-Toolkit mit komfortabler Audio- und MIDI-Integration und Schnittstellen zu den üblichen Audio- und MIDI-Plugin-Systemen. Ein wichtiges Merkmal ist, dass es normalerweise statisch gelinkt wird. Es gibt keine gepflegte ABI. Es hat noch weitere Nachteile: Sprachunterstützung und Screenreader sind relativ neu.
Ich mags nicht, aber ich komme nicht drum herum.
Und: Es gibt für mich keine Entscheidungsfreiheit bezüglich Plugins und JUCE-Versionen. Wenn die JUCE-Version nicht stimmt, ist die ABI im Eimer und ich muss es einfach hinnehmen.
Wie kriege ich raus, ob es am Plugin-Verbindungscode oder an der Anwendung oder an inkompatible Bibliotheken liegt?
Viele Grüße Tobias.
Am 12.02.22 um 18:51 schrieb Konrad Rosenbaum:
Hi,
vorweg: ich habe keine Ahnung was JUCE ist und welche Link-Anforderungen es hat.
Fast immer sollte man so eine Situation vermeiden. Du hast keinerlei Garantie dass es funktioniert.
Der Runtime-Linker macht ein paar Annahmen zu dem Zeug das er in den Speicher lädt:
- Jede Bibliothek kommt nur einmal vor, der selbe Name kann auf die selbe Datei abgebildet werden
- Niemand kommt auf die tollkühne Idee absichtlich zwei Versionen der selben Bibliothek zu linken
- Unterschiedliche Module, die gelinkt werden, haben auch unterschiedliche Symbole - wenn ich ein Symbol gefunden habe, brauche ich nicht weiter zu suchen.
- Weak-Symbole zeigen auf identische Funktionalität und es ist egal welche Instanz ich wohin verlinke.
Es gibt noch ein paar mehr Annahmen, aber in jedem Fall ist eine Verletzung der Annahmen keine gute Idee und führt zu viel Ärger und Kopfschmerz.
On 12/02/2022 18:14, Tobias Schlemmer wrote:
Ein VST-Plugin-Host wurde mit JUCE version A gebaut. Ein VST-Plugin wurde mid JUCE version B gebaut.
Der VST-Plugin-Host verwendet ein shared object mit JUCE-Symbolen. Das VST-Plugin ist ein shared object mit JUCE-Symbolen.
Wie kann ich herausfinden, ob der Host ausschließlich gegen seine eigenen JUCE-Symbole gelinkt wird und ob das Plugin ausschließlich gegen seine version gelinkt wird.
Host: Du müsstest den Host zwingen seine Symbole gleich beim Laden aufzulösen und nach Möglichkeit die Symbole im Plugin verstecken (visibility=hidden).
Plugin: du hast keine Garantie. Selbst wenn Du statisch linkst, mit private linkage und visibility=hidden. Selbst interne Symbole werden erst zur Laufzeit aufgelöst, weil der Linker vorher nicht weiß an welcher Adresse eine Funktion landen wird. Symbole im Host zu verstecken ist vermutlich keine gute Idee, wenn andere Plugins noch funktionieren sollen. Selbst wenn das gehen sollte ist es keine Garantie dass die versteckten Symbole wirklich auch nur lokal verlinkt werden.
Wenn das VST-SDK das unterstützt könnte ich gcc anweisen, das Plugin mit visibility=hidden zu compilieren.
Beim Host ist mir das nicht so klar.
Außerdem möchte ich gern anhand der shared objects sehen, welche Symbole exportiert werden. Das geht doch irgendwie mit objdump oder nm. Hat das schonmal jemand gemacht? Wie geht das genau?
ldd zeigt Dir welche Bibliotheken gefunden werden und wo sie hingelegt werden.
nm zeigt Dir welche Symbole exportiert und importiert werden, aber nicht wo sie hergeholt werden.
objdump kann Dir relativ low-level alles anzeigen was an Export, Import, Symboltabellen, Relocations etc. in einer Datei drin ist. Aber Du musst selbst wissen was der Runtime-Linker damit anstellt.
Setze die Variable LD_DEBUG=all und starte Dein Programm - auf stderr bekommst Du eine Liste aller Symbolauflösungen so wie sie live passieren.
Du wirst sehen dass Du eine Menge Möglichkeiten hast, aber bis Du diese Möglichkeiten gelernt hast und rausgefunden hast wie Du den Linker dazu bewegst Symbole umzubiegen, zu verstecken, hart zu binden, etc.pp. bist Du wahrscheinlich wesentlich schneller und effektiver fertig wenn Du einfach alles auf eine einheitliche Version von JUCE portierst und identisch linkst.
Je nachdem was JUCE macht kann es auch unmöglich sein es stabil zu machen: Qt zum Beispiel dreht komplett frei wenn man zwei Versionen der Core-Bibliothek in den Speicher lädt.
Konrad
lug-dd@mailman.schlittermann.de