summaryrefslogtreecommitdiff
path: root/binaryview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'binaryview.cpp')
-rw-r--r--binaryview.cpp206
1 files changed, 206 insertions, 0 deletions
diff --git a/binaryview.cpp b/binaryview.cpp
index 62bb6f2b..853e201a 100644
--- a/binaryview.cpp
+++ b/binaryview.cpp
@@ -3817,3 +3817,209 @@ BinaryData::BinaryData(FileMetadata* file, const string& path) :
BinaryData::BinaryData(FileMetadata* file, FileAccessor* accessor) :
BinaryView(BNCreateBinaryDataViewFromFile(file->GetObject(), accessor->GetCallbacks()))
{}
+
+
+Ref<BinaryView> BinaryNinja::OpenView(const std::string& filename, bool updateAnalysis, std::function<bool(size_t, size_t)> progress, Json::Value options)
+{
+ if (!progress)
+ progress = [](size_t, size_t) { return true; };
+
+ // Detect bndb
+ bool isDatabase = false;
+ Ref<BinaryView> view = nullptr;
+
+ if (filename.size() > 6 && filename.substr(filename.size() - 5) == ".bndb")
+ {
+ // Open database, read raw view contents from it
+ static const std::string sqlite_header = "SQLite format 3";
+
+ FILE* f = fopen(filename.c_str(), "rb");
+ if (f == nullptr)
+ return nullptr;
+ char header[0x20];
+ fread(header, 1, sqlite_header.size(), f);
+ fclose(f);
+ header[sqlite_header.size()] = 0;
+
+ if (sqlite_header != header)
+ return nullptr;
+
+ Ref<FileMetadata> file = new FileMetadata(filename);
+ view = file->OpenDatabaseForConfiguration(filename);
+ isDatabase = true;
+ }
+ else
+ {
+ // Open file, read raw contents
+ Ref<FileMetadata> file = new FileMetadata(filename);
+ view = new BinaryData(file, filename);
+ }
+
+ if (!view)
+ return nullptr;
+
+ Ref<BinaryViewType> bvt;
+ Ref<BinaryViewType> universalBvt;
+ for (auto available : BinaryViewType::GetViewTypesForData(view))
+ {
+ if (available->GetName() == "Universal")
+ {
+ universalBvt = available;
+ continue;
+ }
+ if (!bvt && available->GetName() != "Raw")
+ {
+ bvt = available;
+ }
+ }
+
+ // No available views: Load as Mapped
+ if (!bvt)
+ bvt = BinaryViewType::GetByName("Mapped");
+
+ Ref<Settings> defaultSettings = Settings::Instance(bvt->GetName() + "_settings");
+ defaultSettings->DeserializeSchema(Settings::Instance()->SerializeSchema());
+ defaultSettings->SetResourceId(bvt->GetName());
+
+ Ref<Settings> loadSettings;
+ if (isDatabase)
+ {
+ loadSettings = view->GetLoadSettings(bvt->GetName());
+ }
+ if (!loadSettings)
+ {
+ if (universalBvt && options.isMember("files.universal.architecturePreference"))
+ {
+ // Load universal architecture
+ loadSettings = universalBvt->GetLoadSettingsForData(view);
+ if (!loadSettings)
+ {
+ LogError("Could not load entry from Universal image. No load settings!");
+ return nullptr;
+ }
+ std::string architectures = loadSettings->Get<std::string>("loader.universal.architectures");
+
+ std::unique_ptr<Json::CharReader> reader(Json::CharReaderBuilder().newCharReader());
+ Json::Value archList;
+ std::string errors;
+ if (!reader->parse((const char*)architectures.data(), (const char*)architectures.data() + architectures.size(), &archList, &errors))
+ {
+ BinaryNinja::LogError("Error parsing architecture list: %s", errors.data());
+ return nullptr;
+ }
+
+ Json::Value archEntry;
+ for (auto archPref : options["files.universal.architecturePreference"])
+ {
+ for (auto entry : archList)
+ {
+ if (entry["architecture"].asString() == archPref.asString())
+ {
+ archEntry = entry;
+ break;
+ }
+ }
+ if (!archEntry.isNull())
+ break;
+ }
+ if (archEntry.isNull())
+ {
+ std::string error = "Could not load any of:";
+ for (auto archPref : options["files.universal.architecturePreference"])
+ {
+ error += string(" ") + archPref.asString();
+ }
+ error += " from Universal image. Entry not found! Available entries:";
+ for (auto entry : archList)
+ {
+ error += string(" ") + entry["architecture"].asString();
+ }
+ LogError("%s", error.c_str());
+ return nullptr;
+ }
+
+ loadSettings = Settings::Instance(GetUniqueIdentifierString());
+
+ Json::StreamWriterBuilder builder;
+ builder["indentation"] = "";
+ string json = Json::writeString(builder, archEntry["loadSchema"]);
+
+ loadSettings->DeserializeSchema(json);
+ }
+ else
+ {
+ // Load non-universal architecture
+ loadSettings = bvt->GetLoadSettingsForData(view);
+ }
+ }
+
+ if (!loadSettings)
+ {
+ LogError("Could not get load settings for binary view of type '%s'", bvt->GetName().c_str());
+ return nullptr;
+ }
+
+ loadSettings->SetResourceId(bvt->GetName());
+ view->SetLoadSettings(bvt->GetName(), loadSettings);
+
+ for (auto key : options.getMemberNames())
+ {
+ auto value = options[key];
+ if (loadSettings->Contains(key))
+ {
+ Json::StreamWriterBuilder builder;
+ builder["indentation"] = "";
+ string json = Json::writeString(builder, value);
+
+ if (!loadSettings->SetJson(key, json, view))
+ {
+ LogError("Setting: %s set operation failed!", key.c_str());
+ return nullptr;
+ }
+ }
+ else if (defaultSettings->Contains(key))
+ {
+ Json::StreamWriterBuilder builder;
+ builder["indentation"] = "";
+ string json = Json::writeString(builder, value);
+
+ if (!defaultSettings->SetJson(key, json, view))
+ {
+ LogError("Setting: %s set operation failed!", key.c_str());
+ return nullptr;
+ }
+ }
+ else
+ {
+ LogError("Setting: %s not available!", key.c_str());
+ return nullptr;
+ }
+ }
+
+ Ref<BinaryView> bv;
+ if (isDatabase)
+ {
+ view = view->GetFile()->OpenExistingDatabase(filename, progress);
+ if (!view)
+ {
+ LogError("Unable to open existing database with filename %s", filename.c_str());
+ return nullptr;
+ }
+ bv = view->GetFile()->GetViewOfType(bvt->GetName());
+ }
+ else
+ {
+ bv = bvt->Create(view);
+ }
+
+ if (!bv)
+ {
+ return view;
+ }
+ if (updateAnalysis)
+ {
+ bv->UpdateAnalysisAndWait();
+ }
+ return bv;
+}
+