Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add API to remove dynamic entries (ELF)
API Changes (Python / C++):

  * lief.ELF.Binary.remove(DynamicEntry / DYNAMIC_TAGS) - Added
  * lief.ELF.Binary.remove_library
  • Loading branch information
romainthomas committed Sep 12, 2017
1 parent 7dce0f3 commit 1e410e6
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 4 deletions.
18 changes: 18 additions & 0 deletions api/python/ELF/objects/pyBinary.cpp
Expand Up @@ -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")
Expand Down Expand Up @@ -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``",
Expand All @@ -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[]),
"",
Expand Down
13 changes: 13 additions & 0 deletions include/LIEF/ELF/Binary.hpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;

Expand Down
57 changes: 54 additions & 3 deletions src/ELF/Binary.cpp
Expand Up @@ -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_;
}


Expand Down Expand Up @@ -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
// =======

Expand Down Expand Up @@ -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));
}
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion src/ELF/DynamicEntry.cpp
Expand Up @@ -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());
}
Expand Down
29 changes: 29 additions & 0 deletions tests/elf/test_dynamic.py
Expand Up @@ -123,12 +123,41 @@ def remove(self):
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()
Expand Down

0 comments on commit 1e410e6

Please sign in to comment.