From 8b93f9efa0bc65c6615583e25d661b34a3b4668b Mon Sep 17 00:00:00 2001 From: wannacu Date: Tue, 15 Oct 2024 15:01:36 +0800 Subject: [PATCH] Speed up ELF symbol lookup It's too slow to rebuild an ELF object that contains a large number of symbols. This happens because the frequent linear looking up was expensive. --- .gitignore | 1 + examples/cpp/CMakeLists.txt | 2 +- include/LIEF/ELF/Binary.hpp | 7 +++++ src/ELF/Binary.cpp | 60 ++++++++----------------------------- src/ELF/Parser.tcc | 2 ++ 5 files changed, 24 insertions(+), 48 deletions(-) diff --git a/.gitignore b/.gitignore index c4d93c7112..54a8cf9175 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ dist/ api/rust/cargo/target/* api/rust/examples/target/* Cargo.lock +.cache diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt index ffd6939d85..62f0e0e13d 100644 --- a/examples/cpp/CMakeLists.txt +++ b/examples/cpp/CMakeLists.txt @@ -75,7 +75,7 @@ foreach(example ${LIEF_CPP_EXAMPLES}) set_target_properties( ${output_name} PROPERTIES POSITION_INDEPENDENT_CODE ON - CXX_STANDARD 11 + CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON) target_link_libraries(${output_name} PUBLIC LIB_LIEF) diff --git a/include/LIEF/ELF/Binary.hpp b/include/LIEF/ELF/Binary.hpp index c57dbc7fae..f8fcbdf2b9 100644 --- a/include/LIEF/ELF/Binary.hpp +++ b/include/LIEF/ELF/Binary.hpp @@ -16,7 +16,9 @@ #ifndef LIEF_ELF_BINARY_H #define LIEF_ELF_BINARY_H +#include #include +#include #include #include "LIEF/visibility.h" @@ -150,6 +152,9 @@ class LIEF_API Binary : public LIEF::Binary { //! Internal container for storing ELF's Symbol using symbols_t = std::vector>; + //! Internal container for fast lookup of symbols + using symbol_indices_t = std::map; + //! Iterator which outputs the Dynamic Symbol& object using it_dynamic_symbols = ref_iterator; @@ -1021,6 +1026,8 @@ class LIEF_API Binary : public LIEF::Binary { dynamic_entries_t dynamic_entries_; symbols_t dynamic_symbols_; symbols_t symtab_symbols_; + symbol_indices_t dynamic_symbol_indices_; + symbol_indices_t symtab_symbol_indices_; relocations_t relocations_; symbols_version_t symbol_version_table_; symbols_version_requirement_t symbol_version_requirements_; diff --git a/src/ELF/Binary.cpp b/src/ELF/Binary.cpp index 88961d9ffd..4710d223b8 100644 --- a/src/ELF/Binary.cpp +++ b/src/ELF/Binary.cpp @@ -256,21 +256,10 @@ void Binary::remove(Note::TYPE type) { int64_t Binary::symtab_idx(const std::string& name) const { - if (symtab_symbols_.empty()) { + if (!symtab_symbol_indices_.count(name)) { return -1; } - - auto it = std::find_if(symtab_symbols_.begin(), symtab_symbols_.end(), - [&name] (const std::unique_ptr& S) { - return S->name() == name; - } - ); - - if (it == symtab_symbols_.end()) { - return -1; - } - - return std::distance(symtab_symbols_.begin(), it); + return symtab_symbol_indices_.at(name); } int64_t Binary::symtab_idx(const Symbol& sym) const { @@ -282,19 +271,10 @@ int64_t Binary::dynsym_idx(const Symbol& sym) const { } int64_t Binary::dynsym_idx(const std::string& name) const { - if (dynamic_symbols_.empty()) { + if (!dynamic_symbol_indices_.count(name)) { return -1; } - - auto it = std::find_if(dynamic_symbols_.begin(), dynamic_symbols_.end(), - [&name] (const std::unique_ptr& S) { - return S->name() == name; - } - ); - if (it == dynamic_symbols_.end()) { - return -1; - } - return std::distance(dynamic_symbols_.begin(), it); + return dynamic_symbol_indices_.at(name); } @@ -410,27 +390,14 @@ Symbol& Binary::add_exported_function(uint64_t address, const std::string& name) bool Binary::has_dynamic_symbol(const std::string& name) const { - const auto it_symbol = std::find_if( - std::begin(dynamic_symbols_), std::end(dynamic_symbols_), - [&name] (const std::unique_ptr& s) { - return s->name() == name; - } - ); - - return it_symbol != std::end(dynamic_symbols_); + return dynamic_symbol_indices_.count(name); } const Symbol* Binary::get_dynamic_symbol(const std::string& name) const { - const auto it_symbol = std::find_if( - std::begin(dynamic_symbols_), std::end(dynamic_symbols_), - [&name] (const std::unique_ptr& s) { - return s->name() == name; - }); - - if (it_symbol == std::end(dynamic_symbols_)) { + if (!dynamic_symbol_indices_.count(name)) { return nullptr; } - return it_symbol->get(); + return dynamic_symbols_[dynamic_symbol_indices_.at(name)].get(); } Symbol* Binary::get_dynamic_symbol(const std::string& name) { @@ -438,15 +405,10 @@ Symbol* Binary::get_dynamic_symbol(const std::string& name) { } const Symbol* Binary::get_symtab_symbol(const std::string& name) const { - const auto it_symbol = std::find_if( - std::begin(symtab_symbols_), std::end(symtab_symbols_), - [&name] (const std::unique_ptr& s) { - return s->name() == name; - }); - if (it_symbol == std::end(symtab_symbols_)) { + if (!symtab_symbol_indices_.count(name)) { return nullptr; } - return it_symbol->get(); + return symtab_symbols_[symtab_symbol_indices_.at(name)].get(); } @@ -569,6 +531,7 @@ void Binary::remove_symtab_symbol(Symbol* symbol) { return; } + symtab_symbol_indices_.erase((*it_symbol)->name()); symtab_symbols_.erase(it_symbol); } @@ -683,6 +646,7 @@ void Binary::remove_dynamic_symbol(Symbol* symbol) { } } + dynamic_symbol_indices_.erase((*it_symbol)->name()); dynamic_symbols_.erase(it_symbol); } @@ -1575,6 +1539,7 @@ void Binary::strip() { Symbol& Binary::add_symtab_symbol(const Symbol& symbol) { symtab_symbols_.push_back(std::make_unique(symbol)); + symtab_symbol_indices_.insert({symtab_symbols_.back()->name(), symtab_symbols_.size() - 1}); return *symtab_symbols_.back(); } @@ -1591,6 +1556,7 @@ Symbol& Binary::add_dynamic_symbol(const Symbol& symbol, const SymbolVersion* ve sym->symbol_version_ = symver.get(); dynamic_symbols_.push_back(std::move(sym)); + dynamic_symbol_indices_.insert({dynamic_symbols_.back()->name(), dynamic_symbols_.size() - 1}); symbol_version_table_.push_back(std::move(symver)); return *dynamic_symbols_.back(); } diff --git a/src/ELF/Parser.tcc b/src/ELF/Parser.tcc index f6ff4e4310..019e18db77 100644 --- a/src/ELF/Parser.tcc +++ b/src/ELF/Parser.tcc @@ -1198,6 +1198,7 @@ ok_error_t Parser::parse_symtab_symbols(uint64_t offset, uint32_t nb_symbols, } link_symbol_section(*symbol); binary_->symtab_symbols_.push_back(std::move(symbol)); + binary_->symtab_symbol_indices_.insert({binary_->symtab_symbols_.back()->name(), binary_->symtab_symbols_.size() - 1}); } return ok(); } @@ -1257,6 +1258,7 @@ ok_error_t Parser::parse_dynamic_symbols(uint64_t offset) { } link_symbol_section(*symbol); binary_->dynamic_symbols_.push_back(std::move(symbol)); + binary_->dynamic_symbol_indices_.insert({binary_->dynamic_symbols_.back()->name(), binary_->dynamic_symbols_.size() - 1}); } binary_->sizing_info_->dynsym = binary_->dynamic_symbols_.size() * sizeof(Elf_Sym); if (const auto* dt_strsz = binary_->get(DynamicEntry::TAG::STRSZ)) {