Enable 64bit VSTs on Linux

* Remove trial-and-error approach of detecting VST's machine types. Read PE
  headers instead.
* Add RemoteVstPlugin64 to AppImage
This commit is contained in:
Lukas W
2018-06-07 11:07:40 +02:00
parent 3beac2ce7f
commit 9db8cbfb31
7 changed files with 82 additions and 32 deletions

View File

@@ -785,11 +785,6 @@ bool RemoteVstPlugin::load( const std::string & _plugin_file )
{
DWORD error = GetLastError();
debugMessage( "LoadLibrary failed: " + GetErrorAsString(error) );
// give VstPlugin class a chance to start 32 bit version of RemoteVstPlugin
if( GetLastError() == ERROR_BAD_EXE_FORMAT )
{
sendMessage( IdVstBadDllFormat );
}
return false;
}

View File

@@ -26,6 +26,7 @@
#include "communication.h"
#include <QtCore/QtEndian>
#include <QtCore/QDebug>
#include <QDir>
#include <QFileInfo>
@@ -64,6 +65,54 @@
#include "templates.h"
#include "FileDialog.h"
namespace PE
{
// Utilities for reading PE file machine type
// See specification at https://msdn.microsoft.com/library/windows/desktop/ms680547(v=vs.85).aspx
enum MachineType : uint16_t
{
IMAGE_FILE_MACHINE_UNKNOWN = 0x0,
IMAGE_FILE_MACHINE_AMD64 = 0x8664,
IMAGE_FILE_MACHINE_I386 = 0x14c,
};
class FileInfo
{
public:
FileInfo(QString filePath)
: m_file(filePath)
{
m_file.open(QFile::ReadOnly);
m_map = m_file.map(0, m_file.size());
if (m_map == nullptr) {
throw std::runtime_error("Cannot map file");
}
}
~FileInfo()
{
m_file.unmap(m_map);
}
MachineType machineType()
{
int32_t peOffset = qFromLittleEndian(* reinterpret_cast<int32_t*>(m_map + 0x3C));
uchar* peSignature = m_map + peOffset;
if (memcmp(peSignature, "PE\0\0", 4)) {
throw std::runtime_error("Invalid PE file");
}
uchar * coffHeader = peSignature + 4;
uint16_t machineType = qFromLittleEndian(* reinterpret_cast<uint16_t*>(coffHeader));
return static_cast<MachineType>(machineType);
}
private:
QFile m_file;
uchar* m_map;
};
}
class vstSubWin : public QMdiSubWindow
{
public:
@@ -93,22 +142,32 @@ VstPlugin::VstPlugin( const QString & _plugin ) :
m_embedMethod( gui
? ConfigManager::inst()->vstEmbedMethod()
: "headless" ),
m_badDllFormat( false ),
m_version( 0 ),
m_currentProgram()
{
setSplittedChannels( true );
#ifdef LMMS_BUILD_WIN64
tryLoad( "RemoteVstPlugin64" );
if( m_badDllFormat )
{
m_badDllFormat = false;
#endif
tryLoad( "RemoteVstPlugin32" );
#ifdef LMMS_BUILD_WIN64
PE::MachineType machineType;
try {
PE::FileInfo peInfo(_plugin);
machineType = peInfo.machineType();
} catch (std::runtime_error& e) {
qCritical() << "Error while determining PE file's machine type: " << e.what();
machineType = PE::IMAGE_FILE_MACHINE_UNKNOWN;
}
switch(machineType)
{
case PE::IMAGE_FILE_MACHINE_AMD64:
tryLoad( "RemoteVstPlugin64" );
break;
case PE::IMAGE_FILE_MACHINE_I386:
tryLoad( "RemoteVstPlugin32" );
break;
default:
m_failed = true;
return;
}
#endif
setTempo( Engine::getSong()->getTempo() );
@@ -390,10 +449,6 @@ bool VstPlugin::processMessage( const message & _m )
{
switch( _m.id )
{
case IdVstBadDllFormat:
m_badDllFormat = true;
break;
case IdVstPluginWindowID:
m_pluginWindowID = _m.getInt();
break;

View File

@@ -139,8 +139,6 @@ private:
QSize m_pluginGeometry;
const QString m_embedMethod;
bool m_badDllFormat;
QString m_name;
int m_version;
QString m_vendorString;

View File

@@ -70,7 +70,6 @@ enum VstRemoteMessageIDs
// remoteVstPlugin -> vstPlugin
IdVstFailedLoadingPlugin,
IdVstBadDllFormat,
IdVstPluginWindowID,
IdVstPluginEditorGeometry,
IdVstPluginName,