mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-07 20:10:13 +02:00
76 lines
2.6 KiB
C++
76 lines
2.6 KiB
C++
#include "plugins.h"
|
|
|
|
#include <fstream>
|
|
#include <sstream>
|
|
|
|
namespace fs = boost::filesystem;
|
|
|
|
LibArchitecture find_dll_architecture(const fs::path& plugin_path) {
|
|
std::ifstream file(plugin_path, std::ifstream::binary | std::ifstream::in);
|
|
|
|
// The linker will place the offset where the PE signature is placed at the
|
|
// end of the MS-DOS stub, at offset 0x3c
|
|
uint32_t pe_signature_offset;
|
|
file.seekg(0x3c);
|
|
file.read(reinterpret_cast<char*>(&pe_signature_offset),
|
|
sizeof(pe_signature_offset));
|
|
|
|
// The PE32 signature will be followed by a magic number that indicates the
|
|
// target architecture of the binary
|
|
uint32_t pe_signature;
|
|
uint16_t machine_type;
|
|
file.seekg(pe_signature_offset);
|
|
file.read(reinterpret_cast<char*>(&pe_signature), sizeof(pe_signature));
|
|
file.read(reinterpret_cast<char*>(&machine_type), sizeof(machine_type));
|
|
|
|
constexpr char expected_pe_signature[4] = {'P', 'E', '\0', '\0'};
|
|
if (pe_signature !=
|
|
*reinterpret_cast<const uint32_t*>(expected_pe_signature)) {
|
|
throw std::runtime_error("'" + plugin_path.string() +
|
|
"' is not a valid .dll file");
|
|
}
|
|
|
|
// These constants are specified in
|
|
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#machine-types
|
|
switch (machine_type) {
|
|
case 0x014c: // IMAGE_FILE_MACHINE_I386
|
|
return LibArchitecture::dll_32;
|
|
break;
|
|
case 0x8664: // IMAGE_FILE_MACHINE_AMD64
|
|
case 0x0000: // IMAGE_FILE_MACHINE_UNKNOWN
|
|
return LibArchitecture::dll_64;
|
|
break;
|
|
}
|
|
|
|
// When compiled without optimizations, GCC 9.3 will warn that the function
|
|
// does not return if we put this in a `default:` case instead.
|
|
std::ostringstream error_msg;
|
|
error_msg << "'" << plugin_path
|
|
<< "' is neither a x86 nor a x86_64 PE32 file. Actual "
|
|
"architecture: 0x"
|
|
<< std::hex << machine_type;
|
|
throw std::runtime_error(error_msg.str());
|
|
}
|
|
|
|
PluginType plugin_type_from_string(const std::string& plugin_type) {
|
|
if (plugin_type == "VST2") {
|
|
return PluginType::vst2;
|
|
} else if (plugin_type == "VST3") {
|
|
return PluginType::vst3;
|
|
} else {
|
|
return PluginType::unknown;
|
|
}
|
|
}
|
|
|
|
std::string plugin_type_to_string(const PluginType& plugin_type) {
|
|
// We'll capitalize the acronyms because this is also our human readable
|
|
// format
|
|
if (plugin_type == PluginType::vst2) {
|
|
return "VST2";
|
|
} else if (plugin_type == PluginType::vst3) {
|
|
return "VST3";
|
|
} else {
|
|
return "<unknown>";
|
|
}
|
|
}
|