mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-01 21:17:44 -05:00
api: Refactored providers to allow for loading interfaces and config views
This commit is contained in:
@@ -130,7 +130,7 @@ namespace hex::plugin::builtin::prv {
|
||||
::close(handle);
|
||||
#endif
|
||||
|
||||
this->open(this->m_path);
|
||||
this->open();
|
||||
}
|
||||
|
||||
size_t FileProvider::getActualSize() const {
|
||||
@@ -156,8 +156,11 @@ namespace hex::plugin::builtin::prv {
|
||||
return result;
|
||||
}
|
||||
|
||||
void FileProvider::open(const std::string &path) {
|
||||
void FileProvider::setPath(const std::string &path) {
|
||||
this->m_path = path;
|
||||
}
|
||||
|
||||
bool FileProvider::open() {
|
||||
this->m_fileStatsValid = stat(this->m_path.data(), &this->m_fileStats) == 0;
|
||||
|
||||
this->m_readable = true;
|
||||
@@ -194,12 +197,12 @@ namespace hex::plugin::builtin::prv {
|
||||
};
|
||||
|
||||
if (this->m_file == nullptr || this->m_file == INVALID_HANDLE_VALUE) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
this->m_mapping = CreateFileMapping(this->m_file, nullptr, PAGE_READWRITE, fileSize.HighPart, fileSize.LowPart, nullptr);
|
||||
if (this->m_mapping == nullptr || this->m_mapping == INVALID_HANDLE_VALUE) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto mappingCleanup = SCOPE_GUARD {
|
||||
@@ -211,7 +214,7 @@ namespace hex::plugin::builtin::prv {
|
||||
this->m_mappedFile = MapViewOfFile(this->m_mapping, FILE_MAP_ALL_ACCESS, 0, 0, this->m_fileSize);
|
||||
if (this->m_mappedFile == nullptr) {
|
||||
this->m_readable = false;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
fileCleanup.release();
|
||||
@@ -220,7 +223,7 @@ namespace hex::plugin::builtin::prv {
|
||||
ProjectFile::setFilePath(this->m_path);
|
||||
|
||||
#else
|
||||
this->m_file = ::open(this->m_path.data(), O_RDWR);
|
||||
this->m_file = ::open(this->m_path.data(), O_RDWR);
|
||||
if (this->m_file == -1) {
|
||||
this->m_file = ::open(this->m_path.data(), O_RDONLY);
|
||||
this->m_writable = false;
|
||||
@@ -228,14 +231,21 @@ namespace hex::plugin::builtin::prv {
|
||||
|
||||
if (this->m_file == -1) {
|
||||
this->m_readable = false;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
this->m_fileSize = this->m_fileStats.st_size;
|
||||
|
||||
this->m_mappedFile = mmap(nullptr, this->m_fileSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, this->m_file, 0);
|
||||
this->m_mappedFile = ::mmap(nullptr, this->m_fileSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, this->m_file, 0);
|
||||
if (this->m_mappedFile == nullptr) {
|
||||
::close(this->m_file);
|
||||
this->m_file = -1;
|
||||
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileProvider::close() {
|
||||
|
||||
@@ -77,6 +77,19 @@ namespace hex::plugin::builtin::prv {
|
||||
return data;
|
||||
}
|
||||
|
||||
void writeMemory(Socket &socket, u64 address, const void *buffer, size_t size) {
|
||||
std::vector<u8> bytes(size);
|
||||
std::memcpy(bytes.data(), buffer, size);
|
||||
|
||||
std::string byteString = crypt::encode16(bytes);
|
||||
|
||||
std::string packet = createPacket(hex::format("M{:X},{:X}:{}", address, size, byteString));
|
||||
|
||||
socket.writeString(packet);
|
||||
|
||||
auto receivedPacket = socket.readString(3);
|
||||
}
|
||||
|
||||
bool enableNoAckMode(Socket &socket) {
|
||||
socket.writeString(createPacket("QStartNoAckMode"));
|
||||
|
||||
@@ -104,7 +117,7 @@ namespace hex::plugin::builtin::prv {
|
||||
}
|
||||
|
||||
GDBProvider::~GDBProvider() {
|
||||
this->disconnect();
|
||||
this->close();
|
||||
}
|
||||
|
||||
|
||||
@@ -135,9 +148,9 @@ namespace hex::plugin::builtin::prv {
|
||||
|
||||
offset -= this->getBaseAddress();
|
||||
|
||||
u64 alignedOffset = offset - (offset & 0xFFF);
|
||||
u64 alignedOffset = offset - (offset % CacheLineSize);
|
||||
|
||||
{
|
||||
if (size <= CacheLineSize) {
|
||||
std::scoped_lock lock(this->m_cacheLock);
|
||||
|
||||
const auto &cacheLine = std::find_if(this->m_cache.begin(), this->m_cache.end(), [&](auto &line){
|
||||
@@ -154,7 +167,15 @@ namespace hex::plugin::builtin::prv {
|
||||
}
|
||||
|
||||
if (cacheLine != this->m_cache.end())
|
||||
std::memcpy(buffer, &cacheLine->data[0] + (offset & 0xFFF), size);
|
||||
std::memcpy(buffer, &cacheLine->data[0] + (offset % CacheLineSize), size);
|
||||
} else {
|
||||
while (size > 0) {
|
||||
size_t readSize = std::min(size, CacheLineSize);
|
||||
this->readRaw(offset, buffer, readSize);
|
||||
|
||||
size -= readSize;
|
||||
offset += readSize;
|
||||
}
|
||||
}
|
||||
|
||||
for (u64 i = 0; i < size; i++)
|
||||
@@ -166,7 +187,12 @@ namespace hex::plugin::builtin::prv {
|
||||
}
|
||||
|
||||
void GDBProvider::write(u64 offset, const void *buffer, size_t size) {
|
||||
if ((offset - this->getBaseAddress()) > (this->getActualSize() - size) || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
offset -= this->getBaseAddress();
|
||||
|
||||
gdb::writeMemory(this->m_socket, offset, buffer, size);
|
||||
}
|
||||
|
||||
void GDBProvider::readRaw(u64 offset, void *buffer, size_t size) {
|
||||
@@ -178,7 +204,10 @@ namespace hex::plugin::builtin::prv {
|
||||
}
|
||||
|
||||
void GDBProvider::writeRaw(u64 offset, const void *buffer, size_t size) {
|
||||
if ((offset - this->getBaseAddress()) > (this->getActualSize() - size) || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
gdb::writeMemory(this->m_socket, offset, buffer, size);
|
||||
}
|
||||
|
||||
void GDBProvider::save() {
|
||||
@@ -200,7 +229,7 @@ namespace hex::plugin::builtin::prv {
|
||||
std::string GDBProvider::getName() const {
|
||||
std::string address, port;
|
||||
|
||||
if (this->m_ipAddress.empty()) {
|
||||
if (!this->isConnected()) {
|
||||
address = "-";
|
||||
port = "-";
|
||||
} else {
|
||||
@@ -212,19 +241,18 @@ namespace hex::plugin::builtin::prv {
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> GDBProvider::getDataInformation() const {
|
||||
return { };
|
||||
return {
|
||||
{ "hex.builtin.provider.gdb.server"_lang, hex::format("{}:{}", this->m_ipAddress, this->m_port) },
|
||||
};
|
||||
}
|
||||
|
||||
void GDBProvider::connect(const std::string &address, u16 port) {
|
||||
this->m_socket.connect(address, port);
|
||||
bool GDBProvider::open() {
|
||||
this->m_socket.connect(this->m_ipAddress, this->m_port);
|
||||
if (!gdb::enableNoAckMode(this->m_socket)) {
|
||||
this->m_socket.disconnect();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
this->m_ipAddress = address;
|
||||
this->m_port = port;
|
||||
|
||||
if (this->m_socket.isConnected()) {
|
||||
this->m_cacheUpdateThread = std::thread([this]() {
|
||||
auto cacheLine = this->m_cache.begin();
|
||||
@@ -250,10 +278,14 @@ namespace hex::plugin::builtin::prv {
|
||||
std::this_thread::sleep_for(100ms);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void GDBProvider::disconnect() {
|
||||
void GDBProvider::close() {
|
||||
this->m_socket.disconnect();
|
||||
|
||||
if (this->m_cacheUpdateThread.joinable()) {
|
||||
@@ -261,8 +293,20 @@ namespace hex::plugin::builtin::prv {
|
||||
}
|
||||
}
|
||||
|
||||
bool GDBProvider::isConnected() {
|
||||
bool GDBProvider::isConnected() const {
|
||||
return this->m_socket.isConnected();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GDBProvider::drawLoadInterface() {
|
||||
ImGui::InputText("hex.builtin.view.gdb.ip"_lang, this->m_ipAddress.data(), this->m_ipAddress.capacity(), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &this->m_ipAddress);
|
||||
ImGui::InputInt("hex.builtin.view.gdb.port"_lang, &this->m_port, 0, 0);
|
||||
|
||||
if (this->m_port < 0)
|
||||
this->m_port = 0;
|
||||
else if (this->m_port > 0xFFFF)
|
||||
this->m_port = 0xFFFF;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "content/views/view_constants.hpp"
|
||||
#include "content/views/view_store.hpp"
|
||||
#include "content/views/view_diff.hpp"
|
||||
#include "content/views/view_gdb.hpp"
|
||||
#include "content/views/view_provider_settings.hpp"
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace hex::plugin::builtin {
|
||||
ContentRegistry::Views::add<ViewConstants>();
|
||||
ContentRegistry::Views::add<ViewStore>();
|
||||
ContentRegistry::Views::add<ViewDiff>();
|
||||
ContentRegistry::Views::add<ViewGDB>();
|
||||
ContentRegistry::Views::add<ViewProviderSettings>();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
#include "content/views/view_gdb.hpp"
|
||||
|
||||
#include "content/providers/gdb_provider.hpp"
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewGDB::ViewGDB() : hex::View("hex.builtin.view.gdb.name") {
|
||||
this->m_address.reserve(3 * 4 + 4);
|
||||
this->m_port = 0;
|
||||
}
|
||||
|
||||
void ViewGDB::drawContent() {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.gdb.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
ImGui::Header("hex.builtin.view.gdb.settings"_lang);
|
||||
ImGui::InputText("hex.builtin.view.gdb.ip"_lang, this->m_address.data(), this->m_address.capacity(), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &this->m_address);
|
||||
ImGui::InputInt("hex.builtin.view.gdb.port"_lang, &this->m_port, 0, 0);
|
||||
|
||||
if (this->m_port < 0)
|
||||
this->m_port = 0;
|
||||
else if (this->m_port > 0xFFFF)
|
||||
this->m_port = 0xFFFF;
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
auto provider = dynamic_cast<prv::GDBProvider*>(hex::ImHexApi::Provider::get());
|
||||
if (provider != nullptr) {
|
||||
if (!provider->isConnected()) {
|
||||
if (ImGui::Button("hex.builtin.view.gdb.connect"_lang)) {
|
||||
provider->connect(this->m_address, this->m_port);
|
||||
}
|
||||
} else {
|
||||
if (ImGui::Button("hex.builtin.view.gdb.disconnect"_lang)) {
|
||||
provider->disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
bool ViewGDB::hasViewMenuItemEntry() {
|
||||
return this->isAvailable();
|
||||
}
|
||||
|
||||
bool ViewGDB::isAvailable() {
|
||||
auto provider = hex::ImHexApi::Provider::get();
|
||||
|
||||
return provider != nullptr && dynamic_cast<prv::GDBProvider*>(provider) != nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -713,8 +713,13 @@ namespace hex::plugin::builtin {
|
||||
hex::prv::Provider *provider = nullptr;
|
||||
EventManager::post<RequestCreateProvider>("hex.builtin.provider.file", &provider);
|
||||
|
||||
if (auto fileProvider = dynamic_cast<prv::FileProvider*>(provider))
|
||||
fileProvider->open(path);
|
||||
if (auto fileProvider = dynamic_cast<prv::FileProvider*>(provider)) {
|
||||
fileProvider->setPath(path);
|
||||
if (!fileProvider->open()) {
|
||||
View::showErrorPopup("hex.builtin.view.hexeditor.error.open"_lang);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!provider->isWritable()) {
|
||||
this->m_memoryEditor.ReadOnly = true;
|
||||
|
||||
@@ -51,23 +51,18 @@ namespace hex::plugin::builtin {
|
||||
EventManager::unsubscribe<EventFileUnloaded>(this);
|
||||
}
|
||||
|
||||
static float calculateEntropy(std::array<ImU64, 256> &valueCounts, size_t numBytes) {
|
||||
static float calculateEntropy(std::array<ImU64, 256> &valueCounts, size_t blockSize) {
|
||||
float entropy = 0;
|
||||
|
||||
if (numBytes == 0)
|
||||
return 0.0F;
|
||||
for (auto count : valueCounts) {
|
||||
if (count == 0) continue;
|
||||
|
||||
std::array<float, 256> floatValueCounts{ 0 };
|
||||
std::copy(valueCounts.begin(), valueCounts.end(), floatValueCounts.begin());
|
||||
float probability = static_cast<float>(count) / blockSize;
|
||||
|
||||
for (u16 i = 0; i < 256; i++) {
|
||||
floatValueCounts[i] /= float(numBytes);
|
||||
|
||||
if (floatValueCounts[i] > 0)
|
||||
entropy -= (floatValueCounts[i] * std::log2(floatValueCounts[i]));
|
||||
entropy += probability * std::log2(probability);
|
||||
}
|
||||
|
||||
return entropy / 8;
|
||||
return (-entropy) / 8; // log2(256) = 8
|
||||
}
|
||||
|
||||
void ViewInformation::analyze() {
|
||||
@@ -93,7 +88,10 @@ namespace hex::plugin::builtin {
|
||||
blockValueCounts[buffer[j]]++;
|
||||
this->m_valueCounts[buffer[j]]++;
|
||||
}
|
||||
|
||||
this->m_blockEntropy.push_back(calculateEntropy(blockValueCounts, this->m_blockSize));
|
||||
|
||||
this->m_bytesAnalyzed = i;
|
||||
}
|
||||
|
||||
this->m_averageEntropy = calculateEntropy(this->m_valueCounts, provider->getSize());
|
||||
@@ -128,20 +126,23 @@ namespace hex::plugin::builtin {
|
||||
}, this->m_analyzing);
|
||||
|
||||
if (this->m_analyzing) {
|
||||
ImGui::SameLine();
|
||||
ImGui::TextSpinner("hex.builtin.view.information.analyzing"_lang);
|
||||
ImGui::ProgressBar(this->m_bytesAnalyzed / static_cast<double>(provider->getSize()));
|
||||
} else {
|
||||
ImGui::NewLine();
|
||||
ImGui::NewLine();
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.region"_lang);
|
||||
ImGui::Separator();
|
||||
|
||||
for (auto &[name, value] : provider->getDataInformation()) {
|
||||
ImGui::LabelText(name.c_str(), "%s", value.c_str());
|
||||
}
|
||||
|
||||
if (this->m_dataValid) {
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.region"_lang);
|
||||
ImGui::Separator();
|
||||
|
||||
for (auto &[name, value] : provider->getDataInformation()) {
|
||||
ImGui::LabelText(name.c_str(), "%s", value.c_str());
|
||||
}
|
||||
|
||||
ImGui::LabelText("hex.builtin.view.information.region"_lang, "0x%llx - 0x%llx", this->m_analyzedRegion.first, this->m_analyzedRegion.second);
|
||||
|
||||
ImGui::NewLine();
|
||||
@@ -169,8 +170,8 @@ namespace hex::plugin::builtin {
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImGui::GetColorU32(ImGuiCol_WindowBg));
|
||||
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.distribution"_lang);
|
||||
ImPlot::SetNextPlotLimits(0, 256, 0, float(*std::max_element(this->m_valueCounts.begin(), this->m_valueCounts.end())) * 1.1F, ImGuiCond_Always);
|
||||
if (ImPlot::BeginPlot("##distribution", "Address", "Count", ImVec2(-1,0), ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect, ImPlotAxisFlags_Lock, ImPlotAxisFlags_Lock)) {
|
||||
ImPlot::SetNextPlotLimits(0, 256, 0.5, float(*std::max_element(this->m_valueCounts.begin(), this->m_valueCounts.end())) * 1.1F, ImGuiCond_Always);
|
||||
if (ImPlot::BeginPlot("##distribution", "Address", "Count", ImVec2(-1,0), ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect, ImPlotAxisFlags_Lock, ImPlotAxisFlags_Lock | ImPlotAxisFlags_LogScale)) {
|
||||
static auto x = []{
|
||||
std::array<ImU64, 256> result{ 0 };
|
||||
std::iota(result.begin(), result.end(), 0);
|
||||
@@ -188,7 +189,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.entropy"_lang);
|
||||
|
||||
ImPlot::SetNextPlotLimits(0, this->m_blockEntropy.size(), -0.1, 1.1, ImGuiCond_Always);
|
||||
if (ImPlot::BeginPlot("##entropy", "Address", "Entropy", ImVec2(-1,0), ImPlotFlags_CanvasOnly, ImPlotAxisFlags_Lock | ImPlotAxisFlags_NoTickLabels, ImPlotAxisFlags_Lock)) {
|
||||
if (ImPlot::BeginPlot("##entropy", "Address", "Entropy", ImVec2(-1,0), ImPlotFlags_CanvasOnly | ImPlotFlags_AntiAliased, ImPlotAxisFlags_Lock | ImPlotAxisFlags_NoTickLabels, ImPlotAxisFlags_Lock)) {
|
||||
ImPlot::PlotLine("##entropy_line", this->m_blockEntropy.data(), this->m_blockEntropy.size());
|
||||
|
||||
if (ImPlot::DragLineX("Position", &this->m_entropyHandlePosition, false)) {
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
#include "content/views/view_provider_settings.hpp"
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewProviderSettings::ViewProviderSettings() : hex::View("hex.builtin.view.provider_settings.name") {
|
||||
EventManager::subscribe<EventProviderCreated>(this, [](hex::prv::Provider *provider){
|
||||
if (provider->hasLoadInterface())
|
||||
EventManager::post<RequestOpenPopup>(View::toWindowName("hex.builtin.view.provider_settings.load_popup"));
|
||||
});
|
||||
}
|
||||
|
||||
ViewProviderSettings::~ViewProviderSettings() {
|
||||
EventManager::unsubscribe<EventProviderCreated>(this);
|
||||
}
|
||||
|
||||
void ViewProviderSettings::drawContent() {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.provider_settings.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
auto provider = hex::ImHexApi::Provider::get();
|
||||
|
||||
if (provider != nullptr)
|
||||
provider->drawInterface();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void ViewProviderSettings::drawAlwaysVisible() {
|
||||
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
|
||||
if (ImGui::BeginPopupModal(View::toWindowName("hex.builtin.view.provider_settings.load_popup").c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
|
||||
auto provider = hex::ImHexApi::Provider::get();
|
||||
|
||||
if (provider != nullptr) {
|
||||
provider->drawLoadInterface();
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::Button("hex.common.open"_lang)) {
|
||||
if (provider->open())
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("hex.common.cancel"_lang)) {
|
||||
ImHexApi::Provider::remove(provider);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
bool ViewProviderSettings::hasViewMenuItemEntry() {
|
||||
return this->isAvailable();
|
||||
}
|
||||
|
||||
bool ViewProviderSettings::isAvailable() {
|
||||
auto provider = hex::ImHexApi::Provider::get();
|
||||
|
||||
return provider != nullptr && provider->hasInterface();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -678,6 +678,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.provider.file", "Datei Provider" },
|
||||
{ "hex.builtin.provider.gdb", "GDB Server Provider" },
|
||||
{ "hex.builtin.provider.gdb.name", "GDB Server <{0}:{1}>" },
|
||||
{ "hex.builtin.provider.gdb.server", "Server" },
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -681,6 +681,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.provider.file", "File Provider" },
|
||||
{ "hex.builtin.provider.gdb", "GDB Server Provider" },
|
||||
{ "hex.builtin.provider.gdb.name", "GDB Server <{0}:{1}>" },
|
||||
{ "hex.builtin.provider.gdb.server", "Server" },
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -675,6 +675,7 @@ namespace hex::plugin::builtin {
|
||||
//{ "hex.builtin.provider.file", "File Provider" },
|
||||
//{ "hex.builtin.provider.gdb", "GDB Server Provider" },
|
||||
//{ "hex.builtin.provider.gdb.name", "GDB Server <{0}:{1}>" },
|
||||
//{ "hex.builtin.provider.gdb.server", "Server" },
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -677,6 +677,7 @@ namespace hex::plugin::builtin {
|
||||
//{ "hex.builtin.provider.file", "File Provider" },
|
||||
//{ "hex.builtin.provider.gdb", "GDB Server Provider" },
|
||||
//{ "hex.builtin.provider.gdb.name", "GDB Server <{0}:{1}>" },
|
||||
//{ "hex.builtin.provider.gdb.server", "Server" },
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user