4
0
mirror of https://github.com/QuasarApp/LIEF.git synced 2025-05-11 11:09:32 +00:00

Add API to remove dynamic entries (ELF)

API Changes (Python / C++):

  * lief.ELF.Binary.remove(DynamicEntry / DYNAMIC_TAGS) - Added
  * lief.ELF.Binary.remove_library
This commit is contained in:
Romain Thomas 2017-09-12 13:57:51 +02:00
parent 7dce0f30ac
commit 1e410e6c95
5 changed files with 115 additions and 4 deletions
api/python/ELF/objects
include/LIEF/ELF
src/ELF
tests/elf

@ -292,6 +292,16 @@ void init_ELF_Binary_class(py::module& m) {
"segment"_a, "size"_a,
py::return_value_policy::reference)
.def("remove",
static_cast<void (Binary::*)(const DynamicEntry&)>(&Binary::remove),
"Remove the given " RST_CLASS_REF(lief.ELF.DynamicEntry) " from the dynamic table",
"dynamic_entry"_a)
.def("remove",
static_cast<void (Binary::*)(DYNAMIC_TAGS)>(&Binary::remove),
"Remove **all** " RST_CLASS_REF(lief.ELF.DynamicEntry) " with the given " RST_CLASS_REF(lief.ELF.DYNAMIC_TAGS) "",
"tag"_a)
.def_property_readonly("has_notes",
&Binary::has_notes,
"``True`` if the binary contains notes")
@ -338,6 +348,11 @@ void init_ELF_Binary_class(py::module& m) {
"Check if the given library name exists in the current binary",
"library_name"_a)
.def("remove_library",
&Binary::remove_library,
"Remove the given library",
"library_name"_a)
.def("get_library",
static_cast<no_const_func<DynamicEntryLibrary&, const std::string&>>(&Binary::get_library),
"Return the " RST_CLASS_REF(lief.ELF.DynamicEntryLibrary) " with the given ``name``",
@ -350,6 +365,9 @@ void init_ELF_Binary_class(py::module& m) {
.def(py::self += DynamicEntry())
.def(py::self -= DynamicEntry())
.def(py::self -= DYNAMIC_TAGS())
.def("__getitem__",
static_cast<Segment& (Binary::*)(SEGMENT_TYPES)>(&Binary::operator[]),
"",

@ -101,8 +101,15 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
it_dynamic_entries dynamic_entries(void);
it_const_dynamic_entries dynamic_entries(void) const;
//! @brief Add the given dynamic entry and return the entry added
DynamicEntry& add(const DynamicEntry& entry);
//! @brief Remove the given dynamic entry
void remove(const DynamicEntry& entry);
//! @brief Remove **all** dynamic entries with the given tag
void remove(DYNAMIC_TAGS tag);
//! @brief Return binary's dynamic symbols
it_symbols dynamic_symbols(void);
it_const_symbols dynamic_symbols(void) const;
@ -257,6 +264,9 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
//! @brief Add a library as dependency
DynamicEntryLibrary& add_library(const std::string& library_name);
//! @brief Remove the given library
void remove_library(const std::string& library_name);
//! @brief Get the library object (DynamicEntryLibrary) from the given name
DynamicEntryLibrary& get_library(const std::string& library_name);
@ -404,6 +414,9 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
Binary& operator+=(const Section& section);
Binary& operator+=(const Segment& segment);
Binary& operator-=(const DynamicEntry& entry);
Binary& operator-=(DYNAMIC_TAGS tag);
Segment& operator[](SEGMENT_TYPES type);
const Segment& operator[](SEGMENT_TYPES type) const;

@ -137,11 +137,11 @@ std::vector<std::string> Binary::get_abstract_imported_libraries(void) const {
// ===============
it_dynamic_entries Binary::dynamic_entries(void) {
return it_dynamic_entries{std::ref(this->dynamic_entries_)};
return this->dynamic_entries_;
}
it_const_dynamic_entries Binary::dynamic_entries(void) const {
return it_const_dynamic_entries{std::cref(this->dynamic_entries_)};
return this->dynamic_entries_;
}
@ -211,6 +211,38 @@ DynamicEntry& Binary::add(const DynamicEntry& entry) {
}
void Binary::remove(const DynamicEntry& entry) {
auto&& it_entry = std::find_if(
std::begin(this->dynamic_entries_),
std::end(this->dynamic_entries_),
[&entry] (const DynamicEntry* e) {
return *e == entry;
});
if (it_entry == std::end(this->dynamic_entries_)) {
std::stringstream ss;
ss << entry;
throw not_found("Can't find '" + ss.str() + "' in the dynamic table!");
}
delete *it_entry;
this->dynamic_entries_.erase(it_entry);
}
void Binary::remove(DYNAMIC_TAGS tag) {
for (auto&& it = std::begin(this->dynamic_entries_);
it != std::end(this->dynamic_entries_);) {
if ((*it)->tag() == tag) {
delete *it;
it = this->dynamic_entries_.erase(it);
} else {
++it;
}
}
}
// Symbols
// =======
@ -1606,6 +1638,11 @@ DynamicEntryLibrary& Binary::add_library(const std::string& library_name) {
}
void Binary::remove_library(const std::string& library_name) {
this->remove(this->get_library(library_name));
}
DynamicEntryLibrary& Binary::get_library(const std::string& library_name) {
return const_cast<DynamicEntryLibrary&>(static_cast<const Binary*>(this)->get_library(library_name));
}
@ -1636,7 +1673,8 @@ bool Binary::has_library(const std::string& name) const {
return it_needed != std::end(this->dynamic_entries_);
}
// Operator+=
// ==========
Binary& Binary::operator+=(const DynamicEntry& entry) {
this->add(entry);
return *this;
@ -1652,7 +1690,20 @@ Binary& Binary::operator+=(const Segment& segment) {
return *this;
}
// Operator -=
// ===========
Binary& Binary::operator-=(const DynamicEntry& entry) {
this->remove(entry);
return *this;
}
Binary& Binary::operator-=(DYNAMIC_TAGS tag) {
this->remove(tag);
return *this;
}
// Operator[]
// ==========
Segment& Binary::operator[](SEGMENT_TYPES type) {
return this->get(type);
}

@ -90,7 +90,7 @@ void DynamicEntry::array(const std::vector<uint64_t>&) {
}
void DynamicEntry::accept(Visitor& visitor) const {
visitor.visit(*this); // Double dispatch to avoid down-casting
visitor(*this); // Double dispatch to avoid down-casting
visitor.visit(this->value());
visitor.visit(this->tag());
}

@ -123,12 +123,41 @@ class LibAddSample(object):
if os.path.isdir(self.directory):
shutil.rmtree(self.directory)
def __del__(self):
self.remove()
class TestDynamic(TestCase):
def setUp(self):
self.logger = logging.getLogger(__name__)
def test_remove_library(self):
sample = LibAddSample()
libadd = lief.parse(sample.libadd)
binadd = lief.parse(sample.binadd)
libadd_needed = binadd.get_library("libadd.so")
binadd -= libadd_needed
self.assertFalse(binadd.has_library("libadd.so"))
def test_remove_tag(self):
sample = LibAddSample()
libadd = lief.parse(sample.libadd)
binadd = lief.parse(sample.binadd)
self.logger.debug("BEFORE")
list(map(lambda e : self.logger.debug(e), binadd.dynamic_entries))
self.logger.debug("")
binadd -= lief.ELF.DYNAMIC_TAGS.NEEDED
self.logger.debug("AFTER")
list(map(lambda e : self.logger.debug(e), binadd.dynamic_entries))
self.logger.debug("")
self.assertTrue(all(e.tag != lief.ELF.DYNAMIC_TAGS.NEEDED for e in binadd.dynamic_entries))
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
def test_change_libname(self):
sample = LibAddSample()