From 67c6b8ba06b4cff11b1661092944586f2fa6c682 Mon Sep 17 00:00:00 2001 From: Matthew McGill <mhollismcgill@gmail.com> Date: Thu, 4 Oct 2018 15:35:05 +0000 Subject: [PATCH] Interface changes Former-commit-id: d11ee2a0bc2d48d2305abfe9522540efd79a930b --- libIRDB/include/libIRDB-util.hpp | 2 +- libIRDB/include/util/IRDB_Objects.hpp | 69 +++++++ libIRDB/include/util/IR_Files.hpp | 46 ----- libIRDB/src/util/IRDB_Objects.cpp | 275 ++++++++++++++++++++++++++ libIRDB/src/util/IR_Files.cpp | 97 --------- libIRDB/src/util/SConscript | 2 +- 6 files changed, 346 insertions(+), 145 deletions(-) create mode 100644 libIRDB/include/util/IRDB_Objects.hpp delete mode 100644 libIRDB/include/util/IR_Files.hpp create mode 100644 libIRDB/src/util/IRDB_Objects.cpp delete mode 100644 libIRDB/src/util/IR_Files.cpp diff --git a/libIRDB/include/libIRDB-util.hpp b/libIRDB/include/libIRDB-util.hpp index 3abc9a34a..dad1f7ead 100644 --- a/libIRDB/include/libIRDB-util.hpp +++ b/libIRDB/include/libIRDB-util.hpp @@ -36,7 +36,7 @@ namespace libIRDB #include <util/insn_preds.hpp> #include <util/IBT_Provenance.hpp> #include <util/params.hpp> -#include <util/IR_Files.hpp> +#include <util/IRDB_Objects.hpp> }; diff --git a/libIRDB/include/util/IRDB_Objects.hpp b/libIRDB/include/util/IRDB_Objects.hpp new file mode 100644 index 000000000..41f062525 --- /dev/null +++ b/libIRDB/include/util/IRDB_Objects.hpp @@ -0,0 +1,69 @@ +#ifndef IRDB_Objects_h +#define IRDB_Objects_h + +#include <map> +#include <utility> +#include <memory> + + +// TODO: Should really use unordered maps but was getting build errors + + +// *** A toolchain step should NOT delete pointers to any variant, file IR, or file object stored +// in a IRFiles_t object. I have made pointers shared where possible to communicate this. *** +class IRDBObjects_t +{ + public: + IRDBObjects_t() + { + // set up interface to the sql server + BaseObj_t::SetInterface(&pqxx_interface); + }; + ~IRDBObjects_t(); + + // Add/delete file IRs for a variant. Takes in the base ID of the + // file (File_t) that the FileIR_t is paired with. + // Cannot delete a file IR if it is also owned outside this object. + // When deleting file IRs, have the option to write back to the DB. + // If the write fails, the IR is still deleted. + int AddFileIR(db_id_t variant_id, db_id_t file_id); + int DeleteFileIR(db_id_t file_id, bool write_to_DB); + // Add or delete a variant + // When deleting a variant, have the option to write back to the DB. + // Cannot delete a variant if it or its files are also owned outside this object. + // If the write fails, the variant is still deleted. + // Writing a variant does NOT write its files' IRs, but DOES delete them! + int AddVariant(db_id_t variant_id); + int DeleteVariant(db_id_t variant_id, bool write_to_DB); + + // get a variant + // returns shared_ptr(NULL) if no such variant + std::shared_ptr<VariantID_t> GetVariant(db_id_t variant_id); + // get a file IR + // returns shared_ptr(NULL) if no such file IR + std::shared_ptr<FileIR_t> GetFileIR(db_id_t file_id); + // get a file + // returns shared_ptr(NULL) if no such file + std::shared_ptr<File_t> GetFile(db_id_t file_id); + // Get DB interface + pqxxDB_t* GetDBInterface(); + + // Write back all variants and file IRs stored in this IRFiles_t object. + // Also removes all variants and file IRs even if some writes fail. + // Returns 1 if any writes fail. + // Does NOT commit changes. + bool WriteBackAll(void); + + private: + pqxxDB_t pqxx_interface; + // maps for speed of finding needed files, file IRs and/or variants + // that have already been read from the DB + + // maps variant id to variant + std::map<db_id_t, std::shared_ptr<VariantID_t>> variant_map; + // maps file id to (file, file ir) + std::map<db_id_t, std::pair<std::shared_ptr<File_t>, std::shared_ptr<FileIR_t>>> file_IR_map; +}; + +#endif + diff --git a/libIRDB/include/util/IR_Files.hpp b/libIRDB/include/util/IR_Files.hpp deleted file mode 100644 index 346826f09..000000000 --- a/libIRDB/include/util/IR_Files.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef IR_Files_h -#define IR_Files_h - -// TODO: This should really use unordered maps and sets, -// but I was having trouble building with those. -#include <map> -#include <utility> -#include <memory> -#include <set> - -// If our toolchain use paradigm changes, this class can be extended -// to support adding, removing, writing back, and getting individual file IRs -// in a variant (may require adding more maps). - -// *** A toolchain step should NOT delete pointers to any variant, file IR, or file object stored -// in a IRFiles_t object. I have made pointers shared where possible to communicate this. *** -class IRFiles_t -{ - public: - IRFiles_t() {}; - ~IRFiles_t(); - - // Add/remove file IRs. - // Adding file IRs also adds the variant the files belong to. - // Removing file IRs also removes the variant the files belong to. - // When removing file IRs, have the option to write back to the DB. - int AddFileIRs(db_id_t variant_id); - int RemoveFileIRs(db_id_t variant_id, bool write_to_DB); - - // get a variant - std::shared_ptr<VariantID_t> GetVariant(db_id_t variant_id); - // get file IRs (returns a shared ptr to a set of shared ptrs to file IRs) - std::shared_ptr<std::set<std::shared_ptr<FileIR_t>>> GetFileIRs(db_id_t variant_id); - - // Write back all variants and file IRs stored in this IRFiles_t object. - int WriteBackAll(void); - - private: - // maps for speed of finding needed file IRs and/or variants - // that have already been read from the DB - std::map<db_id_t, std::shared_ptr<VariantID_t>> variant_map; - std::map<db_id_t, std::shared_ptr<std::set<std::shared_ptr<FileIR_t>>>> file_IRs_map; - -}; - -#endif diff --git a/libIRDB/src/util/IRDB_Objects.cpp b/libIRDB/src/util/IRDB_Objects.cpp new file mode 100644 index 000000000..fccb82458 --- /dev/null +++ b/libIRDB/src/util/IRDB_Objects.cpp @@ -0,0 +1,275 @@ +#include <map> +#include <libIRDB-core.hpp> +#include <libIRDB-util.hpp> +#include <utils.hpp> +#include <utility> +#include <memory> +#include <assert.h> + + +using namespace libIRDB; +using namespace std; + + +IRDBObjects_t::~IRDBObjects_t() +{ + // All dynamically allocated members (DB objects) + // are held as shared pointers and don't need to be + // explicitly deleted. +} + + +int IRDBObjects_t::AddFileIR(db_id_t variant_id, db_id_t file_id) +{ + map<db_id_t, pair<shared_ptr<File_t>, shared_ptr<FileIR_t>>>::iterator + it = file_IR_map.find(file_id); + + if(it == file_IR_map.end()) + { + return 1; + } + else + { + if(it->second.second == NULL) + { + File_t* the_file = (it->second.first).get(); + assert(the_file != NULL); + + assert(variant_map.find(variant_id) != variant_map.end()); + VariantID_t& the_variant = *(variant_map.at(variant_id).get()); + + it->second.second = make_shared<FileIR_t>(the_variant, the_file); + assert(it->second.second != NULL); + } + return 0; + } +} + + +int IRDBObjects_t::DeleteFileIR(db_id_t file_id, bool write_to_DB) +{ + int ret_status = 0; + + map<db_id_t, pair<shared_ptr<File_t>, shared_ptr<FileIR_t>>>::iterator + it = file_IR_map.find(file_id); + + if(it == file_IR_map.end()) + { + ret_status = 1; + } + else + { + if(it->second.second != NULL) + { + assert(it->second.second.unique()); + + if(write_to_DB) + { + shared_ptr<File_t> the_file = it->second.first; + assert(the_file != NULL); + + try + { + cout<<"Writing changes for "<<the_file->GetURL()<<endl; + (it->second.second)->WriteToDB(); + } + catch (DatabaseError_t pnide) + { + cerr << "Unexpected database error: " << pnide << "file url: " << the_file->GetURL() << endl; + ret_status = 2; + } + catch (...) + { + cerr << "Unexpected error file url: " << the_file->GetURL() << endl; + ret_status = 2; + } + } + (it->second.second).reset(); + } + } + + return ret_status; +} + + +int IRDBObjects_t::AddVariant(db_id_t variant_id) +{ + shared_ptr<VariantID_t> the_variant = make_shared<VariantID_t>(variant_id); + assert(the_variant->IsRegistered()==true); + + pair<db_id_t, shared_ptr<VariantID_t>> var_pair = make_pair(variant_id, the_variant); + variant_map.insert(var_pair); + + // add files + for(set<File_t*>::iterator it=the_variant->GetFiles().begin(); + it!=the_variant->GetFiles().end(); + ++it + ) + { + shared_ptr<File_t> curr_file(*it); + shared_ptr<FileIR_t> curr_file_IR; + + pair<shared_ptr<File_t>, shared_ptr<FileIR_t>> file_IR_pair = make_pair(curr_file, curr_file_IR); + pair<db_id_t, pair<shared_ptr<File_t>, shared_ptr<FileIR_t>>> file_map_pair = make_pair((*it)->GetBaseID(), file_IR_pair); + + file_IR_map.insert(file_map_pair); + } + + return 0; +} + + +int IRDBObjects_t::DeleteVariant(db_id_t variant_id, bool write_to_DB) +{ + int ret_status = 0; + map<db_id_t, shared_ptr<VariantID_t>>::iterator var_it = variant_map.find(variant_id); + + if(var_it == variant_map.end()) + { + ret_status = 1; + } + else + { + bool files_being_shared = false; + for(set<File_t*>::iterator file_it=var_it->second->GetFiles().begin(); + file_it!=var_it->second->GetFiles().end(); + ++file_it + ) + { + assert(file_IR_map.find((*file_it)->GetBaseID()) != file_IR_map.end()); + pair<shared_ptr<File_t>, shared_ptr<FileIR_t>> file_IR_pair = file_IR_map.at((*file_it)->GetBaseID()); + if(!file_IR_pair.first.unique() || !file_IR_pair.second.unique()) + { + files_being_shared = true; + } + } + + assert(!files_being_shared); + assert(var_it->second.unique()); + + if(write_to_DB) + { + try + { + cout<<"Writing changes for variant "<<variant_id<<endl; + var_it->second->WriteToDB(); + } + catch (DatabaseError_t pnide) + { + cerr << "Unexpected database error: " << pnide << "variant ID: " << variant_id << endl; + ret_status = 2; + } + catch (...) + { + cerr << "Unexpected error variant ID: " << variant_id << endl; + ret_status = 2; + } + } + // remove files and file IRs + for(set<File_t*>::iterator file_it2=var_it->second->GetFiles().begin(); + file_it2!=var_it->second->GetFiles().end(); + ++file_it2 + ) + { + file_IR_map.erase((*file_it2)->GetBaseID()); + } + + // remove variant + variant_map.erase(variant_id); + } + + return ret_status; +} + + +bool IRDBObjects_t::WriteBackAll(void) +{ + bool all_successes = true; + + // Write back FileIRs + for(map<db_id_t, pair<shared_ptr<File_t>, shared_ptr<FileIR_t>>>::iterator + it = file_IR_map.begin(); + it != file_IR_map.end(); + ++it + ) + { + int result = IRDBObjects_t::DeleteFileIR((it->second.first)->GetBaseID(), true); + if(result != 0) + { + all_successes = false; + } + } + + // Write back Variants + for(map<db_id_t, shared_ptr<VariantID_t>>::iterator + it2 = variant_map.begin(); + it2 != variant_map.end(); + ++it2 + ) + { + int result = IRDBObjects_t::DeleteVariant((it2->second)->GetBaseID(), true); + if(result != 0) + { + all_successes = false; + } + } + + return all_successes; +} + + +shared_ptr<VariantID_t> IRDBObjects_t::GetVariant(db_id_t variant_id) +{ + map<db_id_t, shared_ptr<VariantID_t>>::iterator it = variant_map.find(variant_id); + + if(it == variant_map.end()) + { + shared_ptr<VariantID_t> null_var; + return null_var; + } + else + { + return it->second; + } +} + + +shared_ptr<FileIR_t> IRDBObjects_t::GetFileIR(db_id_t file_id) +{ + map<db_id_t, pair<shared_ptr<File_t>, shared_ptr<FileIR_t>>>::iterator + it = file_IR_map.find(file_id); + + if(it == file_IR_map.end()) + { + shared_ptr<FileIR_t> null_fileIR; + return null_fileIR; + } + else + { + return it->second.second; + } +} + + +shared_ptr<File_t> IRDBObjects_t::GetFile(db_id_t file_id) +{ + map<db_id_t, pair<shared_ptr<File_t>, shared_ptr<FileIR_t>>>::iterator + it = file_IR_map.find(file_id); + + if(it == file_IR_map.end()) + { + shared_ptr<File_t> null_file; + return null_file; + } + else + { + return it->second.first; + } +} + + +pqxxDB_t* IRDBObjects_t::GetDBInterface() +{ + return &pqxx_interface; +} + diff --git a/libIRDB/src/util/IR_Files.cpp b/libIRDB/src/util/IR_Files.cpp deleted file mode 100644 index 1a51f0bcc..000000000 --- a/libIRDB/src/util/IR_Files.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include <map> -#include <libIRDB-core.hpp> -#include <libIRDB-util.hpp> -#include <utils.hpp> -#include <utility> -#include <memory> -#include <iterator> - - -using namespace libIRDB; -using namespace std; - - -IRFiles_t::~IRFiles_t() -{ - file_IR_map.clear(); // doesn't write back to DB -} - - -void IRFiles_t::AddFileIR(FileIR_t& IR_ref) -{ - File_t* file_ptr = IR_ref.GetFile(); - - assert(file_ptr); - - file_IR_map.insert(pair<File_t*, shared_ptr<FileIR_t>>(file_ptr, shared_ptr<FileIR_t>(&IR_ref))); -} - - -// may throw a database error exception if writing back to DB. -// If the write back fails, the FileIR will not be destroyed. -void IRFiles_t::RemoveFileIR(FileIR_t& IR_ref, bool write_to_DB) -{ - if(!HasFileIR(IR_ref)) - return; - - if(write_to_DB) - IR_ref.WriteToDB(); - - File_t* file_ptr = IR_ref.GetFile(); - - assert(file_ptr); - - file_IR_map.erase(file_ptr); -} - - -// may throw a database error exception if writing back to DB. -// If the write back fails, the FileIR will not be destroyed. -void IRFiles_t::RemoveFileIR(File_t& file_ref, bool write_to_DB) -{ - if(!HasFileIR(file_ref)) - return; - - if(write_to_DB) - GetFileIR(file_ref)->WriteToDB(); - - file_IR_map.erase(&file_ref); -} - - -bool IRFiles_t::HasFileIR(File_t& file_ref) -{ - map<File_t*, shared_ptr<FileIR_t>>::iterator got = file_IR_map.find(&file_ref); - - if(got == file_IR_map.end()) - return false; - else - return true; -} - - -bool IRFiles_t::HasFileIR(FileIR_t& IR_ref) -{ - File_t* file_ptr = IR_ref.GetFile(); - - assert(file_ptr); - - map<File_t*, shared_ptr<FileIR_t>>::iterator got = file_IR_map.find(file_ptr); - - if(got == file_IR_map.end()) - return false; - else - return true; -} - - -FileIR_t* IRFiles_t::GetFileIR(File_t& file_ref) -{ - map<File_t*, shared_ptr<FileIR_t>>::iterator got = file_IR_map.find(&file_ref); - - if(got == file_IR_map.end()) - return NULL; - else - return (got->second).get(); -} - diff --git a/libIRDB/src/util/SConscript b/libIRDB/src/util/SConscript index 6c9385cf2..673d28ffa 100644 --- a/libIRDB/src/util/SConscript +++ b/libIRDB/src/util/SConscript @@ -10,7 +10,7 @@ files= ''' insn_preds.cpp IBT_Provenance.cpp params.cpp - IR_Files.cpp + IRDB_Objects.cpp ''' cpppath=''' $SECURITY_TRANSFORMS_HOME/include/ -- GitLab